Coverage Report

Created: 2025-06-10 06:56

/src/ghostpdl/psi/zfapi.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2001-2025 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
/* Font API client */
18
19
#include "stdlib.h"             /* abs() */
20
21
#include "memory_.h"
22
#include "math_.h"
23
#include "stat_.h"              /* include before definition of esp macro, bug 691123 */
24
#include "string_.h"
25
#include "ghost.h"
26
#include "gp.h"
27
#include "oper.h"
28
#include "gxdevice.h"
29
#include "gxfont.h"
30
#include "gxfont1.h"
31
#include "gxchar.h"
32
#include "gzpath.h"
33
#include "gxpath.h"
34
#include "gxfcache.h"
35
#include "gxchrout.h"
36
#include "gximask.h"
37
#include "gscoord.h"
38
#include "gspaint.h"
39
#include "gsfont.h"
40
#include "gspath.h"
41
#include "bfont.h"
42
#include "dstack.h"
43
#include "estack.h"
44
#include "ichar.h"
45
#include "idict.h"
46
#include "iname.h"
47
#include "ifont.h"
48
#include "icid.h"
49
#include "igstate.h"
50
#include "icharout.h"
51
52
#include "ifapi.h"
53
#include "iplugin.h"
54
#include "store.h"
55
#include "gzstate.h"
56
/* #include "gdevpsf.h" */
57
#include "stream.h"             /* for files.h */
58
#include "gscrypt1.h"
59
#include "gxfcid.h"
60
#include "gsstype.h"
61
#include "gxchar.h"             /* for st_gs_show_enum */
62
#include "ipacked.h"            /* for packed_next */
63
#include "iddict.h"
64
#include "ifont42.h"            /* for string_array_access_proc */
65
#include "gdebug.h"
66
#include "gsimage.h"
67
#include "gxcldev.h"
68
#include "gxdevmem.h"
69
70
#include "gxfapi.h"
71
72
/* -------------------------------------------------------- */
73
74
typedef struct sfnts_reader_s sfnts_reader;
75
struct sfnts_reader_s
76
{
77
    ref *sfnts;
78
    const gs_memory_t *memory;
79
    const byte *p;
80
    long index;
81
    uint offset;
82
    uint length;
83
    int error;
84
         byte(*rbyte) (sfnts_reader *r);
85
         ushort(*rword) (sfnts_reader *r);
86
         ulong(*rlong) (sfnts_reader *r);
87
    int (*rstring) (sfnts_reader *r, byte *v, int length);
88
    void (*seek) (sfnts_reader *r, ulong pos);
89
};
90
91
static void
92
sfnts_next_elem(sfnts_reader *r)
93
24
{
94
24
    ref s;
95
24
    int code;
96
97
24
    if (r->error < 0)
98
0
        return;
99
24
    do {
100
24
      r->index++;
101
24
      code = array_get(r->memory, r->sfnts, r->index, &s);
102
24
        if (code < 0) {
103
2
            r->error = code;
104
2
            return;
105
2
        }
106
22
        if (!r_has_type(&s, t_string)) {
107
0
            r->error = gs_note_error(gs_error_typecheck);
108
0
            return;
109
0
        }
110
22
      r->p = s.value.const_bytes;
111
22
      r->length = r_size(&s) & ~(uint) 1; /* See Adobe Technical Note # 5012, section 4.2. */
112
22
    } while (r->length == 0);
113
22
    r->offset = 0;
114
22
}
115
116
static inline byte
117
sfnts_reader_rbyte_inline(sfnts_reader *r)
118
432
{
119
432
    if (r->offset >= r->length)
120
0
        sfnts_next_elem(r);
121
432
    return ((r->error < 0) ? 0 : r->p[r->offset++]);
122
432
}
123
124
static byte
125
sfnts_reader_rbyte(sfnts_reader *r)
126
0
{                               /* old compiler compatibility */
127
0
    return (sfnts_reader_rbyte_inline(r));
128
0
}
129
130
32
#define SFNTS_READER_RBYTE_TO_USHORT(r) ((ulong)sfnts_reader_rbyte_inline(r))
131
132
static ushort
133
sfnts_reader_rword(sfnts_reader *r)
134
16
{
135
16
    ushort retval;
136
137
16
    retval = SFNTS_READER_RBYTE_TO_USHORT(r) << 8;
138
16
    retval += SFNTS_READER_RBYTE_TO_USHORT(r);
139
140
16
    return retval;
141
16
}
142
143
#undef SFNTS_READER_RBYTE_TO_USHORT
144
145
400
#define SFNTS_READER_RBYTE_TO_ULONG(r) ((ulong)sfnts_reader_rbyte_inline(r))
146
147
static ulong
148
sfnts_reader_rlong(sfnts_reader *r)
149
100
{
150
100
    ulong retval;
151
100
    retval = SFNTS_READER_RBYTE_TO_ULONG(r) << 24;
152
100
    retval += SFNTS_READER_RBYTE_TO_ULONG(r) << 16;
153
100
    retval += SFNTS_READER_RBYTE_TO_ULONG(r) << 8;
154
100
    retval += SFNTS_READER_RBYTE_TO_ULONG(r);
155
100
    return retval;
156
100
}
157
158
#undef SFNTS_READER_RWORD_TO_LONG
159
160
static int
161
sfnts_reader_rstring(sfnts_reader *r, byte *v, int length)
162
34
{
163
34
    int rlength = length;
164
165
34
    if (length <= 0)
166
0
        return (0);
167
36
    while (r->error >= 0) {
168
34
        int l = min(length, r->length - r->offset);
169
170
34
        memcpy(v, r->p + r->offset, l);
171
34
        length -= l;
172
34
        r->offset += l;
173
34
        if (length <= 0)
174
32
            return (rlength);
175
2
        v += l;
176
2
        sfnts_next_elem(r);
177
2
    }
178
2
    return (rlength - length);
179
34
}
180
181
static void
182
sfnts_reader_seek(sfnts_reader *r, ulong pos)
183
2
{                               /* fixme : optimize */
184
2
    ulong skipped = 0;
185
186
2
    r->index = -1;
187
2
    sfnts_next_elem(r);
188
18
    while (skipped + r->length < pos && r->error >= 0) {
189
16
        skipped += r->length;
190
16
        sfnts_next_elem(r);
191
16
    }
192
2
    r->offset = pos - skipped;
193
2
}
194
195
static void
196
sfnts_reader_init(const gs_memory_t *mem, sfnts_reader *r, ref *pdr)
197
4
{
198
4
    r->memory = mem;
199
4
    r->rbyte = sfnts_reader_rbyte;
200
4
    r->rword = sfnts_reader_rword;
201
4
    r->rlong = sfnts_reader_rlong;
202
4
    r->rstring = sfnts_reader_rstring;
203
4
    r->seek = sfnts_reader_seek;
204
4
    r->index = -1;
205
4
    r->error = 0;
206
4
    if (r_type(pdr) != t_dictionary ||
207
4
        dict_find_string(pdr, "sfnts", &r->sfnts) <= 0)
208
0
        r->error = gs_error_undefined;
209
4
    sfnts_next_elem(r);
210
4
}
211
212
/* -------------------------------------------------------- */
213
214
typedef struct sfnts_writer_s sfnts_writer;
215
struct sfnts_writer_s
216
{
217
    byte *buf, *p;
218
    int buf_size;
219
    void (*wbyte) (sfnts_writer *w, byte v);
220
    void (*wword) (sfnts_writer *w, ushort v);
221
    void (*wlong) (sfnts_writer *w, ulong v);
222
    void (*wstring) (sfnts_writer *w, byte *v, int length);
223
};
224
225
static void
226
sfnts_writer_wbyte(sfnts_writer *w, byte v)
227
0
{
228
0
    if (w->buf + w->buf_size < w->p + 1)
229
0
        return;                 /* safety */
230
0
    w->p[0] = v;
231
0
    w->p++;
232
0
}
233
234
static void
235
sfnts_writer_wword(sfnts_writer *w, ushort v)
236
8
{
237
8
    if (w->buf + w->buf_size < w->p + 2)
238
0
        return;                 /* safety */
239
8
    w->p[0] = v / 256;
240
8
    w->p[1] = v % 256;
241
8
    w->p += 2;
242
8
}
243
244
static void
245
sfnts_writer_wlong(sfnts_writer *w, ulong v)
246
38
{
247
38
    if (w->buf + w->buf_size < w->p + 4)
248
0
        return;                 /* safety */
249
38
    w->p[0] = v >> 24;
250
38
    w->p[1] = (v >> 16) & 0xFF;
251
38
    w->p[2] = (v >> 8) & 0xFF;
252
38
    w->p[3] = v & 0xFF;
253
38
    w->p += 4;
254
38
}
255
256
static void
257
sfnts_writer_wstring(sfnts_writer *w, byte *v, int length)
258
14
{
259
14
    if (w->buf + w->buf_size < w->p + length)
260
0
        return;                 /* safety */
261
14
    memcpy(w->p, v, length);
262
14
    w->p += length;
263
14
}
264
265
static const sfnts_writer sfnts_writer_stub = {
266
    0, 0, 0,
267
    sfnts_writer_wbyte,
268
    sfnts_writer_wword,
269
    sfnts_writer_wlong,
270
    sfnts_writer_wstring
271
};
272
273
/* -------------------------------------------------------- */
274
275
static inline bool
276
sfnts_need_copy_table(byte *tag)
277
50
{
278
50
    return (memcmp(tag, "glyf", 4) && memcmp(tag, "glyx", 4) && /* Presents in files created by AdobePS5.dll Version 5.1.2 */
279
50
            memcmp(tag, "loca", 4) && memcmp(tag, "locx", 4) && /* Presents in files created by AdobePS5.dll Version 5.1.2 */
280
50
            memcmp(tag, "cmap", 4));
281
50
}
282
283
static void
284
sfnt_copy_table(sfnts_reader *r, sfnts_writer *w, int length)
285
2
{
286
2
    byte buf[1024];
287
288
4
    while (length > 0 && r->error >= 0) {
289
2
        int l = min(length, sizeof(buf));
290
291
2
        (void)r->rstring(r, buf, l);
292
2
        w->wstring(w, buf, l);
293
2
        length -= l;
294
2
    }
295
2
}
296
297
static int
298
sfnts_copy_except_glyf(sfnts_reader *r, sfnts_writer *w)
299
4
{                               /* Note : TTC is not supported and probably is unuseful for Type 42. */
300
    /* This skips glyf, loca and cmap from copying. */
301
4
    struct
302
4
    {
303
4
        byte tag[4];
304
4
        ulong checkSum, offset, offset_new, length;
305
4
    } tables[40];
306
4
    const ushort alignment = 4; /* Not sure, maybe 2 */
307
4
    ulong version = r->rlong(r);
308
4
    ushort num_tables = r->rword(r);
309
4
    ushort i, num_tables_new = 0;
310
4
    ushort searchRange, entrySelector = 0, rangeShift, v;
311
4
    ulong size_new = 12;
312
313
4
    if (num_tables > countof(tables)) {
314
0
        r->error = gs_note_error(gs_error_invalidfont);
315
0
        return r->error;
316
0
    }
317
318
4
    r->rword(r);                /* searchRange */
319
4
    if (r->error < 0)
320
0
        return r->error;
321
322
4
    r->rword(r);                /* entrySelector */
323
4
    if (r->error < 0)
324
0
        return r->error;
325
326
4
    r->rword(r);                /* rangeShift */
327
4
    if (r->error < 0)
328
0
        return r->error;
329
330
36
    for (i = 0; i < num_tables && r->error >= 0; i++) {
331
32
        (void)r->rstring(r, tables[i].tag, 4);
332
32
        if (r->error < 0)
333
0
            continue;
334
32
        tables[i].checkSum = r->rlong(r);
335
32
        tables[i].offset = r->rlong(r);
336
32
        tables[i].length = r->rlong(r);
337
32
        tables[i].offset_new = size_new;
338
32
        if (sfnts_need_copy_table(tables[i].tag)) {
339
24
            num_tables_new++;
340
24
            size_new +=
341
24
                (tables[i].length + alignment - 1) / alignment * alignment;
342
24
        }
343
32
    }
344
4
    if (r->error < 0)
345
0
        return r->error;
346
4
    size_new += num_tables_new * 16;
347
4
    if (w == 0) {
348
2
        return size_new;
349
2
    }
350
2
    searchRange = v = num_tables_new * 16;
351
16
    for (i = 0; v; i++) {
352
14
        v >>= 1;
353
14
        searchRange |= v;
354
14
        entrySelector++;
355
14
    }
356
2
    searchRange -= searchRange >> 1;
357
2
    rangeShift = num_tables_new * 16 - searchRange;
358
359
2
    w->wlong(w, version);
360
2
    w->wword(w, num_tables_new);
361
2
    w->wword(w, searchRange);
362
2
    w->wword(w, entrySelector);
363
2
    w->wword(w, rangeShift);
364
18
    for (i = 0; i < num_tables; i++) {
365
16
        if (sfnts_need_copy_table(tables[i].tag)) {
366
12
            w->wstring(w, tables[i].tag, 4);
367
12
            w->wlong(w, tables[i].checkSum);
368
12
            w->wlong(w, tables[i].offset_new + num_tables_new * 16);
369
12
            w->wlong(w, tables[i].length);
370
12
        }
371
16
    }
372
4
    for (i = 0; i < num_tables && r->error >= 0; i++) {
373
2
        if (sfnts_need_copy_table(tables[i].tag)) {
374
2
            int k = tables[i].length;
375
376
2
            r->seek(r, tables[i].offset);
377
378
2
            if (w->p - w->buf != tables[i].offset_new + num_tables_new * 16) {
379
0
                r->error = gs_error_invalidfont;       /* the algorithm consistency check */
380
0
                continue;
381
0
            }
382
2
            sfnt_copy_table(r, w, tables[i].length);
383
2
            for (; k & (alignment - 1); k++)
384
0
                w->wbyte(w, 0);
385
2
        }
386
2
    }
387
2
    if (r->error < 0)
388
2
        return r->error;
389
390
0
    return (size_new);
391
2
}
392
393
static int
394
true_type_size(const gs_memory_t *mem, ref *pdr, unsigned long int *length)
395
2
{
396
2
    sfnts_reader r;
397
398
2
    sfnts_reader_init(mem, &r, pdr);
399
2
    *length = sfnts_copy_except_glyf(&r, 0);
400
401
2
    return r.error;
402
2
}
403
404
static int
405
FAPI_FF_serialize_tt_font(gs_fapi_font *ff, void *buf, int buf_size)
406
2
{
407
2
    ref *pdr = pfont_dict(((gs_font_base *) ff->client_font_data2));
408
2
    sfnts_reader r;
409
2
    sfnts_writer w = sfnts_writer_stub;
410
411
2
    w.buf_size = buf_size;
412
2
    w.buf = w.p = buf;
413
2
    sfnts_reader_init(ff->memory, &r, pdr);
414
2
    return sfnts_copy_except_glyf(&r, &w);
415
2
}
416
417
static inline ushort
418
float_to_ushort(float v)
419
432k
{
420
432k
    return ((ushort) (v * 16)); /* fixme : the scale may depend on renderer */
421
432k
}
422
423
/* In general, we assumed that the entries we use below have been validated (at least for type)
424
 * at definefont time. This means validating each entry only once, rather than on every read
425
 * here. Better, for example, for BlendDesignMap which is an array, of arrays, of arrays of
426
 * numbers.
427
 */
428
static int
429
FAPI_FF_get_word(gs_fapi_font *ff, gs_fapi_font_feature var_id, int index, unsigned short *ret)
430
824k
{
431
824k
    gs_font_type1 *pfont = (gs_font_type1 *) ff->client_font_data;
432
824k
    ref *pdr = pfont_dict(((gs_font_base *) ff->client_font_data2));
433
824k
    int code = 0;
434
435
824k
    switch ((int)var_id) {
436
0
        case gs_fapi_font_feature_Weight:
437
0
            *ret = 0;           /* wrong */
438
0
            break;
439
0
        case gs_fapi_font_feature_ItalicAngle:
440
0
            *ret = 0;           /* wrong */
441
0
            break;
442
0
        case gs_fapi_font_feature_IsFixedPitch:
443
0
            *ret = 0;           /* wrong */
444
0
            break;
445
0
        case gs_fapi_font_feature_UnderLinePosition:
446
0
            *ret = 0;           /* wrong */
447
0
            break;
448
0
        case gs_fapi_font_feature_UnderlineThickness:
449
0
            *ret = 0;           /* wrong */
450
0
            break;
451
13.5k
        case gs_fapi_font_feature_FontType:
452
13.5k
            *ret = (pfont->FontType == 2 ? 2 : 1);
453
13.5k
            break;
454
108k
        case gs_fapi_font_feature_FontBBox:
455
108k
            switch (index) {
456
27.0k
                case 0:
457
27.0k
                    *ret = ((ushort) pfont->FontBBox.p.x);
458
27.0k
                    break;
459
27.0k
                case 1:
460
27.0k
                    *ret = ((ushort) pfont->FontBBox.p.y);
461
27.0k
                    break;
462
27.0k
                case 2:
463
27.0k
                    *ret = ((ushort) pfont->FontBBox.q.x);
464
27.0k
                    break;
465
27.0k
                case 3:
466
27.0k
                    *ret = ((ushort) pfont->FontBBox.q.y);
467
27.0k
                    break;
468
0
                default:
469
0
                    code = gs_note_error(gs_error_rangecheck);
470
108k
            }
471
108k
            break;
472
108k
        case gs_fapi_font_feature_BlueValues_count:
473
27.0k
            *ret = pfont->data.BlueValues.count;
474
27.0k
            break;
475
215k
        case gs_fapi_font_feature_BlueValues:
476
215k
            *ret =  (float_to_ushort(pfont->data.BlueValues.values[index]));
477
215k
            break;
478
27.0k
        case gs_fapi_font_feature_OtherBlues_count:
479
27.0k
            *ret = pfont->data.OtherBlues.count;
480
27.0k
            break;
481
0
        case gs_fapi_font_feature_OtherBlues:
482
0
            *ret = (float_to_ushort(pfont->data.OtherBlues.values[index]));
483
0
            break;
484
27.0k
        case gs_fapi_font_feature_FamilyBlues_count:
485
27.0k
            *ret = pfont->data.FamilyBlues.count;
486
27.0k
            break;
487
0
        case gs_fapi_font_feature_FamilyBlues:
488
0
            *ret = (float_to_ushort(pfont->data.FamilyBlues.values[index]));
489
0
            break;
490
27.0k
        case gs_fapi_font_feature_FamilyOtherBlues_count:
491
27.0k
            *ret = pfont->data.FamilyOtherBlues.count;
492
27.0k
            break;
493
0
        case gs_fapi_font_feature_FamilyOtherBlues:
494
0
            *ret = (float_to_ushort(pfont->data.FamilyOtherBlues.values[index]));
495
0
            break;
496
27.0k
        case gs_fapi_font_feature_BlueShift:
497
27.0k
            *ret = float_to_ushort(pfont->data.BlueShift);
498
27.0k
            break;
499
27.0k
        case gs_fapi_font_feature_BlueFuzz:
500
27.0k
            *ret = float_to_ushort(pfont->data.BlueShift);
501
27.0k
            break;
502
27.0k
        case gs_fapi_font_feature_StdHW:
503
27.0k
            *ret = (pfont->data.StdHW.count == 0 ? 0 : float_to_ushort(pfont->data.StdHW.values[0]));   /* UFST bug ? */
504
27.0k
            break;
505
27.0k
        case gs_fapi_font_feature_StdVW:
506
27.0k
            *ret = (pfont->data.StdVW.count == 0 ? 0 : float_to_ushort(pfont->data.StdVW.values[0]));   /* UFST bug ? */
507
27.0k
            break;
508
27.0k
        case gs_fapi_font_feature_StemSnapH_count:
509
27.0k
            *ret = pfont->data.StemSnapH.count;
510
27.0k
            break;
511
54.1k
        case gs_fapi_font_feature_StemSnapH:
512
54.1k
            *ret = float_to_ushort(pfont->data.StemSnapH.values[index]);
513
54.1k
            break;
514
27.0k
        case gs_fapi_font_feature_StemSnapV_count:
515
27.0k
            *ret = pfont->data.StemSnapV.count;
516
27.0k
            break;
517
53.9k
        case gs_fapi_font_feature_StemSnapV:
518
53.9k
            *ret = float_to_ushort(pfont->data.StemSnapV.values[index]);
519
53.9k
            break;
520
27.0k
        case gs_fapi_font_feature_ForceBold:
521
27.0k
            *ret = pfont->data.ForceBold;
522
27.0k
            break;
523
0
        case gs_fapi_font_feature_LanguageGroup:
524
0
            *ret = pfont->data.LanguageGroup;
525
0
            break;
526
0
        case gs_fapi_font_feature_lenIV:
527
0
            *ret = ff->need_decrypt ? 0 : pfont->data.lenIV;
528
0
            break;
529
0
        case gs_fapi_font_feature_GlobalSubrs_count:
530
0
            {
531
0
                ref *Private, *GlobalSubrs;
532
533
0
                if (pfont->FontType == ft_encrypted2) {
534
0
                    if (dict_find_string(pdr, "Private", &Private) <= 0) {
535
0
                        *ret = 0;
536
0
                        break;
537
0
                    }
538
0
                    if (dict_find_string(Private, "GlobalSubrs", &GlobalSubrs) <= 0) {
539
0
                        *ret = 0;
540
0
                        break;
541
0
                    }
542
0
                    *ret = r_size(GlobalSubrs);
543
0
                    break;
544
0
                }
545
0
                *ret = 0;
546
0
                break;
547
0
            }
548
27.0k
        case gs_fapi_font_feature_Subrs_count:
549
27.0k
            {
550
27.0k
                ref *Private, *Subrs;
551
552
27.0k
                if (dict_find_string(pdr, "Private", &Private) <= 0) {
553
0
                    *ret = 0;
554
0
                    break;
555
0
                }
556
27.0k
                if (dict_find_string(Private, "Subrs", &Subrs) <= 0) {
557
0
                    *ret = 0;
558
0
                    break;
559
0
                }
560
27.0k
                *ret = r_size(Subrs);
561
27.0k
                break;
562
27.0k
            }
563
0
        case gs_fapi_font_feature_CharStrings_count:
564
0
            {
565
0
                ref *CharStrings;
566
567
0
                if (dict_find_string(pdr, "CharStrings", &CharStrings) <= 0)
568
0
                    *ret = 0;
569
0
                else
570
0
                    *ret = dict_maxlength(CharStrings);
571
0
                break;
572
27.0k
            }
573
            /* Multiple Master specific */
574
54.1k
        case gs_fapi_font_feature_DollarBlend:
575
54.1k
            {
576
54.1k
                ref *DBlend;
577
578
54.1k
                if (dict_find_string(pdr, "$Blend", &DBlend) <= 0)
579
54.1k
                    *ret = 0;
580
0
                else
581
0
                    *ret = 1;
582
54.1k
                break;
583
27.0k
            }
584
0
        case gs_fapi_font_feature_BlendAxisTypes_count:
585
0
            {
586
0
                ref *Info, *Axes;
587
588
0
                if (dict_find_string(pdr, "FontInfo", &Info) <= 0) {
589
0
                    *ret = 0;
590
0
                    break;
591
0
                }
592
0
                if (dict_find_string(Info, "BlendAxisTypes", &Axes) <= 0) {
593
0
                    *ret = 0;
594
0
                    break;
595
0
                }
596
0
                *ret = r_size(Axes);
597
0
                break;
598
0
            }
599
0
        case gs_fapi_font_feature_BlendFontInfo_count:
600
0
            {
601
0
                ref *Info, *FontInfo;
602
603
0
                if (dict_find_string(pdr, "Blend", &Info) <= 0) {
604
0
                    *ret = 0;
605
0
                    break;
606
0
                }
607
0
                if (dict_find_string(Info, "FontInfo", &FontInfo) <= 0) {
608
0
                    *ret = 0;
609
0
                    break;
610
0
                }
611
0
                *ret = dict_length(FontInfo);
612
0
                break;
613
0
            }
614
0
        case gs_fapi_font_feature_BlendPrivate_count:
615
0
            {
616
0
                ref *Info, *Private;
617
618
0
                if (dict_find_string(pdr, "Blend", &Info) <= 0) {
619
0
                    *ret = 0;
620
0
                    break;
621
0
                }
622
0
                if (dict_find_string(Info, "Private", &Private) <= 0) {
623
0
                    *ret = 0;
624
0
                    break;
625
0
                }
626
0
                *ret = dict_length(Private);
627
0
                break;
628
0
            }
629
0
        case gs_fapi_font_feature_WeightVector_count:
630
0
            {
631
0
                *ret = pfont->data.WeightVector.count;
632
0
                break;
633
0
            }
634
0
        case gs_fapi_font_feature_BlendDesignPositionsArrays_count:
635
0
            {
636
0
                ref *Info, *Array;
637
638
0
                if (dict_find_string(pdr, "FontInfo", &Info) <= 0) {
639
0
                    *ret = 0;
640
0
                    break;
641
0
                }
642
0
                if (dict_find_string(Info, "BlendDesignPositions", &Array) <= 0) {
643
0
                    *ret = 0;
644
0
                    break;
645
0
                }
646
0
                *ret = r_size(Array);
647
0
                break;
648
0
            }
649
0
        case gs_fapi_font_feature_BlendDesignMapArrays_count:
650
0
            {
651
0
                ref *Info, *Array;
652
653
0
                if (dict_find_string(pdr, "FontInfo", &Info) <= 0) {
654
0
                    *ret = 0;
655
0
                    break;
656
0
                }
657
0
                if (dict_find_string(Info, "BlendDesignMap", &Array) <= 0) {
658
0
                    *ret = 0;
659
0
                    break;
660
0
                }
661
0
                *ret = r_size(Array);
662
0
                break;
663
0
            }
664
0
        case gs_fapi_font_feature_BlendDesignMapSubArrays_count:
665
0
            {
666
0
                ref *Info, *Array, SubArray;
667
668
0
                if (dict_find_string(pdr, "FontInfo", &Info) <= 0) {
669
0
                    *ret = 0;
670
0
                    break;
671
0
                }
672
0
                if (dict_find_string(Info, "BlendDesignMap", &Array) <= 0) {
673
0
                    *ret = 0;
674
0
                    break;
675
0
                }
676
0
                if (array_get(ff->memory, Array, index, &SubArray) < 0) {
677
0
                    *ret = 0;
678
0
                    break;
679
0
                }
680
0
                *ret = r_size(&SubArray);
681
0
                break;
682
0
            }
683
0
        case gs_fapi_font_feature_DollarBlend_length:
684
0
            {
685
0
                ref *DBlend, Element, string;
686
0
                int i, length = 0;
687
0
                char Buffer[32];
688
689
0
                if (dict_find_string(pdr, "$Blend", &DBlend) <= 0) {
690
0
                    *ret = 0;
691
0
                    break;
692
0
                }
693
0
                for (i = 0; i < r_size(DBlend); i++) {
694
                    /* When reading the real proc, we add a space between each entry */
695
0
                    length++;
696
0
                    if (array_get(ff->memory, DBlend, i, &Element) < 0) {
697
0
                        length = 0;
698
0
                        break;
699
0
                    }
700
0
                    switch (r_btype(&Element)) {
701
0
                        case t_name:
702
0
                            name_string_ref(ff->memory, &Element, &string);
703
0
                            length += r_size(&string);
704
0
                            break;
705
0
                        case t_real:
706
0
                            gs_snprintf(Buffer, sizeof(Buffer), "%f", Element.value.realval);
707
0
                            length += strlen(Buffer);
708
0
                            break;
709
0
                        case t_integer:
710
0
                            gs_snprintf(Buffer, sizeof(Buffer), "%"PRIpsint, Element.value.intval);
711
0
                            length += strlen(Buffer);
712
0
                            break;
713
0
                        case t_operator:
714
0
                            {
715
0
                                op_def const *op;
716
717
0
                                op = op_index_def(r_size(&Element));
718
0
                                length += strlen(op->oname + 1);
719
0
                            }
720
0
                            break;
721
0
                        default:
722
0
                            break;
723
0
                    }
724
725
0
                    if (length > max_ushort) {
726
0
                        length = 0;
727
0
                        break;
728
0
                    }
729
0
                 }
730
0
                *ret = length;
731
0
                break;
732
0
            }
733
0
        case gs_fapi_font_feature_BlendFontBBox_length:
734
0
            {
735
0
                ref *Blend, *bfbbox, bfbbox0;
736
0
                if (dict_find_string(pdr, "Blend", &Blend) <= 0) {
737
0
                    *ret = 0;
738
0
                    break;
739
0
                }
740
741
0
                if (dict_find_string(Blend, "FontBBox", &bfbbox) <= 0) {
742
0
                    *ret = 0;
743
0
                    break;
744
0
                }
745
0
                if (!r_has_type(bfbbox, t_array) || array_get(ff->memory, bfbbox, 0, &bfbbox0) < 0) {
746
0
                    *ret = 0;
747
0
                    break;
748
0
                }
749
0
                *ret = (ushort)r_size(&bfbbox0);
750
0
                break;
751
0
            }
752
0
        case gs_fapi_font_feature_BlendFontBBox:
753
0
            {
754
0
                ref *Blend, *bfbbox, subbfbbox, val;
755
0
                int aind, ind;
756
0
                if (dict_find_string(pdr, "Blend", &Blend) <= 0) {
757
0
                    *ret = 0;
758
0
                    break;
759
0
                }
760
0
                if (dict_find_string(Blend, "FontBBox", &bfbbox) <= 0) {
761
0
                    *ret = 0;
762
0
                    break;
763
0
                }
764
0
                ind = index % 4;
765
0
                aind = (index - ind) /4;
766
0
                if (array_get(ff->memory, bfbbox, aind, &subbfbbox) < 0) {
767
0
                    *ret = 0;
768
0
                    break;
769
0
                }
770
0
                if (array_get(ff->memory, &subbfbbox, ind, &val) < 0) {
771
0
                    *ret = 0;
772
0
                    break;
773
0
                }
774
775
0
                *ret = (ushort)val.value.intval;
776
0
                break;
777
0
            }
778
0
        case gs_fapi_font_feature_BlendBlueValues_length:
779
0
            {
780
0
                ref *Priv, *Blend, *bbv;
781
0
                if (dict_find_string(pdr, "Blend", &Blend) <= 0) {
782
0
                    *ret = 0;
783
0
                    break;
784
0
                }
785
0
                if (dict_find_string(Blend, "Private", &Priv) <= 0) {
786
0
                    *ret = 0;
787
0
                    break;
788
0
                }
789
0
                if (dict_find_string(Priv, "BlueValues", &bbv) <= 0) {
790
0
                    *ret = 0;
791
0
                    break;
792
0
                }
793
0
                *ret = (ushort)r_size(bbv);
794
0
                break;
795
0
            }
796
0
        case gs_fapi_font_feature_BlendBlueValues_count:
797
0
            {
798
0
                ref *Priv, *Blend, *bbv, sub;
799
800
0
                if (dict_find_string(pdr, "Blend", &Blend) <= 0) {
801
0
                    *ret = 0;
802
0
                    break;
803
0
                }
804
0
                if (dict_find_string(Blend, "Private", &Priv) <= 0) {
805
0
                    *ret = 0;
806
0
                    break;
807
0
                }
808
0
                if (dict_find_string(Priv, "BlueValues", &bbv) <= 0) {
809
0
                    *ret = 0;
810
0
                    break;
811
0
                }
812
0
                if (array_get(ff->memory, bbv, index, &sub) < 0) {
813
0
                    *ret = 0;
814
0
                    break;
815
0
                }
816
0
                *ret = (ushort)r_size(&sub);
817
0
                break;
818
0
            }
819
0
        case gs_fapi_font_feature_BlendBlueValues:
820
0
            {
821
0
                ref *Priv, *Blend, *bbv, sub, r;
822
0
                int aind = 0;
823
0
                if (dict_find_string(pdr, "Blend", &Blend) <= 0) {
824
0
                    *ret = 0;
825
0
                    break;
826
0
                }
827
0
                if (dict_find_string(Blend, "Private", &Priv) <= 0) {
828
0
                    *ret = 0;
829
0
                    break;
830
0
                }
831
0
                if (dict_find_string(Priv, "BlueValues", &bbv) <= 0) {
832
0
                    *ret = 0;
833
0
                    break;
834
0
                }
835
836
0
                while (1) {
837
0
                    if ((code = array_get(ff->memory, bbv, aind++, &sub)) < 0) {
838
0
                        *ret = 0;
839
0
                        break;
840
0
                    }
841
0
                    if (index - (int)r_size(&sub) < 0) {
842
0
                        break;
843
0
                    }
844
0
                    index -= r_size(&sub);
845
0
                }
846
0
                if (code < 0)
847
0
                    break;
848
849
0
                if (array_get(ff->memory, &sub, index, &r) < 0) {
850
0
                    *ret = 0;
851
0
                    break;
852
0
                }
853
854
0
                *ret = (ushort)r.value.intval;
855
0
                break;
856
0
            }
857
0
        case gs_fapi_font_feature_BlendOtherBlues_length:
858
0
            {
859
0
                ref *Priv, *Blend, *bob;
860
0
                if (dict_find_string(pdr, "Blend", &Blend) <= 0) {
861
0
                    *ret = 0;
862
0
                    break;
863
0
                }
864
0
                if (dict_find_string(Blend, "Private", &Priv) <= 0) {
865
0
                    *ret = 0;
866
0
                    break;
867
0
                }
868
0
                if (dict_find_string(Priv, "OtherBlues", &bob) <= 0) {
869
0
                    *ret = 0;
870
0
                    break;
871
0
                }
872
0
                *ret = (ushort)r_size(bob);
873
0
                break;
874
0
            }
875
0
        case gs_fapi_font_feature_BlendOtherBlues_count:
876
0
            {
877
0
                ref *Priv, *Blend, *bob, sub;
878
0
                if (dict_find_string(pdr, "Blend", &Blend) <= 0) {
879
0
                    *ret = 0;
880
0
                    break;
881
0
                }
882
0
                if (dict_find_string(Blend, "Private", &Priv) <= 0) {
883
0
                    *ret = 0;
884
0
                    break;
885
0
                }
886
0
                if (dict_find_string(Priv, "OtherBlues", &bob) <= 0) {
887
0
                    *ret = 0;
888
0
                    break;
889
0
                }
890
891
0
                 if (array_get(ff->memory, bob, index, &sub) < 0) {
892
0
                    *ret = 0;
893
0
                    break;
894
0
                }
895
0
                *ret = (ushort)r_size(&sub);
896
0
                break;
897
0
            }
898
0
        case gs_fapi_font_feature_BlendOtherBlues:
899
0
            {
900
0
                ref *Priv, *Blend, *bob, sub, r;
901
0
                int aind = 0;
902
0
                if (dict_find_string(pdr, "Blend", &Blend) <= 0) {
903
0
                    *ret = 0;
904
0
                    break;
905
0
                }
906
0
                if (dict_find_string(Blend, "Private", &Priv) <= 0) {
907
0
                    *ret = 0;
908
0
                    break;
909
0
                }
910
0
                if (dict_find_string(Priv, "OtherBlues", &bob) <= 0) {
911
0
                    *ret = 0;
912
0
                    break;
913
0
                }
914
915
0
                while (1) {
916
0
                    if ((code = array_get(ff->memory, bob, aind++, &sub)) < 0)
917
0
                        break;
918
0
                    if (index - (int)r_size(&sub) < 0) {
919
0
                        break;
920
0
                    }
921
0
                    index -= r_size(&sub);
922
0
                }
923
0
                if (code < 0) {
924
0
                    *ret = 0;
925
0
                    break;
926
0
                }
927
0
                if (array_get(ff->memory, &sub, index, &r) < 0) {
928
0
                    *ret = 0;
929
0
                    break;
930
0
                }
931
932
0
                *ret = (ushort)r.value.intval;
933
0
                break;
934
0
            }
935
0
        case gs_fapi_font_feature_BlendBlueScale_count:
936
0
            {
937
0
                ref *Priv, *Blend, *bbs;
938
0
                if (dict_find_string(pdr, "Blend", &Blend) <= 0) {
939
0
                    *ret = 0;
940
0
                    break;
941
0
                }
942
0
                if (dict_find_string(Blend, "Private", &Priv) <= 0) {
943
0
                    *ret = 0;
944
0
                    break;
945
0
                }
946
0
                if (dict_find_string(Priv, "BlueScale", &bbs) <= 0) {
947
0
                    *ret = 0;
948
0
                    break;
949
0
                }
950
0
                *ret = (ushort)r_size(bbs);
951
0
                break;
952
0
            }
953
0
        case gs_fapi_font_feature_BlendBlueShift_count:
954
0
            {
955
0
                ref *Priv, *Blend, *bbs;
956
0
                if (dict_find_string(pdr, "Blend", &Blend) <= 0) {
957
0
                    *ret = 0;
958
0
                    break;
959
0
                }
960
0
                if (dict_find_string(Blend, "Private", &Priv) <= 0) {
961
0
                    *ret = 0;
962
0
                    break;
963
0
                }
964
0
                if (dict_find_string(Priv, "BlueShift", &bbs) <= 0) {
965
0
                    *ret = 0;
966
0
                    break;
967
0
                }
968
0
                *ret = (ushort)r_size(bbs);
969
0
                break;
970
0
            }
971
0
        case gs_fapi_font_feature_BlendBlueShift:
972
0
            {
973
0
                ref *Priv, *Blend, *bbs, r;
974
0
                if (dict_find_string(pdr, "Blend", &Blend) <= 0) {
975
0
                    *ret = 0;
976
0
                    break;
977
0
                }
978
0
                if (dict_find_string(Blend, "Private", &Priv) <= 0) {
979
0
                    *ret = 0;
980
0
                    break;
981
0
                }
982
0
                if (dict_find_string(Priv, "BlueShift", &bbs) <= 0) {
983
0
                    *ret = 0;
984
0
                    break;
985
0
                }
986
0
                if (array_get(ff->memory, bbs, index, &r) < 0) {
987
0
                    *ret = 0;
988
0
                    break;
989
0
                }
990
991
0
                *ret = (ushort)r.value.intval;
992
0
                break;
993
0
            }
994
0
        case gs_fapi_font_feature_BlendBlueFuzz_count:
995
0
            {
996
0
                ref *Priv, *Blend, *bbf;
997
0
                if (dict_find_string(pdr, "Blend", &Blend) <= 0) {
998
0
                    *ret = 0;
999
0
                    break;
1000
0
                }
1001
0
                if (dict_find_string(Blend, "Private", &Priv) <= 0) {
1002
0
                    *ret = 0;
1003
0
                    break;
1004
0
                }
1005
0
                if (dict_find_string(Priv, "BlueFuzz", &bbf) <= 0) {
1006
0
                    *ret = 0;
1007
0
                    break;
1008
0
                }
1009
0
                *ret = (ushort)r_size(bbf);
1010
0
                break;
1011
0
            }
1012
0
        case gs_fapi_font_feature_BlendBlueFuzz:
1013
0
            {
1014
0
                ref *Priv, *Blend, *bbf, r;
1015
0
                if (dict_find_string(pdr, "Blend", &Blend) <= 0) {
1016
0
                    *ret = 0;
1017
0
                    break;
1018
0
                }
1019
0
                if (dict_find_string(Blend, "Private", &Priv) <= 0) {
1020
0
                    *ret = 0;
1021
0
                    break;
1022
0
                }
1023
0
                if (dict_find_string(Priv, "BlueFuzz", &bbf) <= 0) {
1024
0
                    *ret = 0;
1025
0
                    break;
1026
0
                }
1027
0
                if (array_get(ff->memory, bbf, index, &r) < 0) {
1028
0
                    *ret = 0;
1029
0
                    break;
1030
0
                }
1031
1032
0
                *ret = (ushort)r.value.intval;
1033
0
                break;
1034
0
            }
1035
0
        case gs_fapi_font_feature_BlendForceBold_count:
1036
0
            {
1037
0
                ref *Priv, *Blend, *bfb;
1038
0
                if (dict_find_string(pdr, "Blend", &Blend) <= 0) {
1039
0
                    *ret = 0;
1040
0
                    break;
1041
0
                }
1042
0
                if (dict_find_string(Blend, "Private", &Priv) <= 0) {
1043
0
                    *ret = 0;
1044
0
                    break;
1045
0
                }
1046
0
                if (dict_find_string(Priv, "ForceBold", &bfb) <= 0) {
1047
0
                    *ret = 0;
1048
0
                    break;
1049
0
                }
1050
0
                *ret = (ushort)r_size(bfb);
1051
0
                break;
1052
0
            }
1053
0
        case gs_fapi_font_feature_BlendForceBold:
1054
0
            {
1055
0
                ref *Priv, *Blend, *bfb, r;
1056
0
                if (dict_find_string(pdr, "Blend", &Blend) <= 0) {
1057
0
                    *ret = 0;
1058
0
                    break;
1059
0
                }
1060
0
                if (dict_find_string(Blend, "Private", &Priv) <= 0) {
1061
0
                    *ret = 0;
1062
0
                    break;
1063
0
                }
1064
0
                if (dict_find_string(Priv, "BlueFuzz", &bfb) <= 0) {
1065
0
                    *ret = 0;
1066
0
                    break;
1067
0
                }
1068
0
                if (array_get(ff->memory, bfb, index, &r) < 0) {
1069
0
                    *ret = 0;
1070
0
                    break;
1071
0
                }
1072
1073
0
                *ret = (ushort)r.value.boolval;
1074
0
            }
1075
0
        case gs_fapi_font_feature_BlendStdHW_length:
1076
0
            {
1077
0
                ref *Priv, *Blend, *stdhw;
1078
0
                if (dict_find_string(pdr, "Blend", &Blend) <= 0) {
1079
0
                    *ret = 0;
1080
0
                    break;
1081
0
                }
1082
0
                if (dict_find_string(Blend, "Private", &Priv) <= 0) {
1083
0
                    *ret = 0;
1084
0
                    break;
1085
0
                }
1086
0
                if (dict_find_string(Priv, "StdHW", &stdhw) <= 0) {
1087
0
                    *ret = 0;
1088
0
                    break;
1089
0
                }
1090
0
                *ret = (ushort)r_size(stdhw);
1091
0
                break;
1092
0
            }
1093
0
        case gs_fapi_font_feature_BlendStdHW_count:
1094
0
            {
1095
0
                ref *Priv, *Blend, *stdhw, sub;
1096
0
                if (dict_find_string(pdr, "Blend", &Blend) <= 0) {
1097
0
                    *ret = 0;
1098
0
                    break;
1099
0
                }
1100
0
                if (dict_find_string(Blend, "Private", &Priv) <= 0) {
1101
0
                    *ret = 0;
1102
0
                    break;
1103
0
                }
1104
0
                if (dict_find_string(Priv, "StdHW", &stdhw) <= 0) {
1105
0
                    *ret = 0;
1106
0
                    break;
1107
0
                }
1108
1109
0
                if (array_get(ff->memory, stdhw, index, &sub) < 0) {
1110
0
                    *ret = 0;
1111
0
                    break;
1112
0
                }
1113
0
                *ret = (ushort)r_size(&sub);
1114
0
                break;
1115
0
            }
1116
0
        case gs_fapi_font_feature_BlendStdHW:
1117
0
            {
1118
0
                ref *Priv, *Blend, *stdhw, sub, r;
1119
0
                int aind = 0;
1120
0
                if (dict_find_string(pdr, "Blend", &Blend) <= 0) {
1121
0
                    *ret = 0;
1122
0
                    break;
1123
0
                }
1124
0
                if (dict_find_string(Blend, "Private", &Priv) <= 0) {
1125
0
                    *ret = 0;
1126
0
                    break;
1127
0
                }
1128
0
                if (dict_find_string(Priv, "StdHW", &stdhw) <= 0) {
1129
0
                    *ret = 0;
1130
0
                    break;
1131
0
                }
1132
1133
0
                while (1) {
1134
0
                    if ((code = array_get(ff->memory, stdhw, aind++, &sub)) < 0)
1135
0
                        break;
1136
0
                    if (index - (int)r_size(&sub) < 0) {
1137
0
                        break;
1138
0
                    }
1139
0
                    index -= r_size(&sub);
1140
0
                }
1141
0
                if (code < 0) {
1142
0
                    *ret = 0;
1143
0
                    break;
1144
0
                }
1145
0
                if (array_get(ff->memory, &sub, index, &r) < 0) {
1146
0
                    *ret = 0;
1147
0
                    break;
1148
0
                }
1149
1150
0
                *ret = (ushort)r.value.intval;
1151
0
                break;
1152
0
            }
1153
0
        case gs_fapi_font_feature_BlendStdVW_length:
1154
0
            {
1155
0
                ref *Priv, *Blend, *stdvw;
1156
0
                if (dict_find_string(pdr, "Blend", &Blend) <= 0) {
1157
0
                    *ret = 0;
1158
0
                    break;
1159
0
                }
1160
0
                if (dict_find_string(Blend, "Private", &Priv) <= 0) {
1161
0
                    *ret = 0;
1162
0
                    break;
1163
0
                }
1164
0
                if (dict_find_string(Priv, "StdVW", &stdvw) <= 0) {
1165
0
                    *ret = 0;
1166
0
                    break;
1167
0
                }
1168
0
                *ret = (ushort)r_size(stdvw);
1169
0
                break;
1170
0
            }
1171
0
        case gs_fapi_font_feature_BlendStdVW_count:
1172
0
            {
1173
0
                ref *Priv, *Blend, *stdvw, sub;
1174
0
                if (dict_find_string(pdr, "Blend", &Blend) <= 0) {
1175
0
                    *ret = 0;
1176
0
                    break;
1177
0
                }
1178
0
                if (dict_find_string(Blend, "Private", &Priv) <= 0) {
1179
0
                    *ret = 0;
1180
0
                    break;
1181
0
                }
1182
1183
0
                if (dict_find_string(Priv, "StdVW", &stdvw) <= 0) {
1184
0
                    *ret = 0;
1185
0
                    break;
1186
0
                }
1187
1188
0
                if (array_get(ff->memory, stdvw, index, &sub) < 0) {
1189
0
                    *ret = 0;
1190
0
                    break;
1191
0
                }
1192
0
                *ret = (ushort)r_size(&sub);
1193
0
                break;
1194
0
            }
1195
0
        case gs_fapi_font_feature_BlendStdVW:
1196
0
            {
1197
0
                ref *Priv, *Blend, *stdvw, sub, r;
1198
0
                int aind = 0;
1199
0
                if (dict_find_string(pdr, "Blend", &Blend) <= 0) {
1200
0
                    *ret = 0;
1201
0
                    break;
1202
0
                }
1203
0
                if (dict_find_string(Blend, "Private", &Priv) <= 0) {
1204
0
                    *ret = 0;
1205
0
                    break;
1206
0
                }
1207
0
                if (dict_find_string(Priv, "StdVW", &stdvw) <= 0) {
1208
0
                    *ret = 0;
1209
0
                    break;
1210
0
                }
1211
1212
0
                while (1) {
1213
0
                    if ((code = array_get(ff->memory, stdvw, aind++, &sub)) < 0)
1214
0
                        break;
1215
0
                    if (index - (int)r_size(&sub) < 0) {
1216
0
                        break;
1217
0
                    }
1218
0
                    index -= r_size(&sub);
1219
0
                }
1220
0
                if (code < 0) {
1221
0
                    *ret = 0;
1222
0
                    break;
1223
0
                }
1224
0
                if (array_get(ff->memory, &sub, index, &r) < 0) {
1225
0
                    *ret = 0;
1226
0
                    break;
1227
0
                }
1228
1229
0
                *ret = (ushort)r.value.intval;
1230
0
                break;
1231
0
            }
1232
0
        case gs_fapi_font_feature_BlendStemSnapH_length:
1233
0
            {
1234
0
                ref *Priv, *Blend, *ssh;
1235
0
                if (dict_find_string(pdr, "Blend", &Blend) <= 0) {
1236
0
                    *ret = 0;
1237
0
                    break;
1238
0
                }
1239
0
                if (dict_find_string(Blend, "Private", &Priv) <= 0) {
1240
0
                    *ret = 0;
1241
0
                    break;
1242
0
                }
1243
0
                if (dict_find_string(Priv, "StemSnapH", &ssh) <= 0) {
1244
0
                    *ret = 0;
1245
0
                    break;
1246
0
                }
1247
0
                *ret = (ushort)r_size(ssh);
1248
0
                break;
1249
0
            }
1250
0
        case gs_fapi_font_feature_BlendStemSnapH_count:
1251
0
            {
1252
0
                ref *Priv, *Blend, *bssh, sub;
1253
0
                if (dict_find_string(pdr, "Blend", &Blend) <= 0) {
1254
0
                    *ret = 0;
1255
0
                    break;
1256
0
                }
1257
0
                if (dict_find_string(Blend, "Private", &Priv) <= 0) {
1258
0
                    *ret = 0;
1259
0
                    break;
1260
0
                }
1261
0
                if (dict_find_string(Priv, "StemSnapH", &bssh) <= 0) {
1262
0
                    *ret = 0;
1263
0
                    break;
1264
0
                }
1265
1266
0
                if (array_get(ff->memory, bssh, index, &sub) < 0) {
1267
0
                    *ret = 0;
1268
0
                    break;
1269
0
                }
1270
0
                *ret = (ushort)r_size(&sub);
1271
0
                break;
1272
0
            }
1273
0
        case gs_fapi_font_feature_BlendStemSnapH:
1274
0
            {
1275
0
                ref *Priv, *Blend, *bssh, sub, r;
1276
0
                int aind = 0;
1277
0
                if (dict_find_string(pdr, "Blend", &Blend) <= 0) {
1278
0
                    *ret = 0;
1279
0
                    break;
1280
0
                }
1281
0
                if (dict_find_string(Blend, "Private", &Priv) <= 0) {
1282
0
                    *ret = 0;
1283
0
                    break;
1284
0
                }
1285
0
                if (dict_find_string(Priv, "StemSnapH", &bssh) <= 0) {
1286
0
                    *ret = 0;
1287
0
                    break;
1288
0
                }
1289
1290
0
                while (1) {
1291
0
                    if ((code = array_get(ff->memory, bssh, aind++, &sub)) < 0)
1292
0
                        break;
1293
0
                    if (index - (int)r_size(&sub) < 0) {
1294
0
                        break;
1295
0
                    }
1296
0
                    index -= r_size(&sub);
1297
0
                }
1298
0
                if (code < 0) {
1299
0
                    *ret = 0;
1300
0
                    break;
1301
0
                }
1302
0
                if (array_get(ff->memory, &sub, index, &r) < 0) {
1303
0
                    *ret = 0;
1304
0
                    break;
1305
0
                }
1306
1307
0
                *ret = (ushort)r.value.intval;
1308
0
                break;
1309
0
            }
1310
0
        case gs_fapi_font_feature_BlendStemSnapV_length:
1311
0
            {
1312
0
                ref *Priv, *Blend, *ssv;
1313
0
                if (dict_find_string(pdr, "Blend", &Blend) <= 0) {
1314
0
                    *ret = 0;
1315
0
                    break;
1316
0
                }
1317
0
                if (dict_find_string(Blend, "Private", &Priv) <= 0) {
1318
0
                    *ret = 0;
1319
0
                    break;
1320
0
                }
1321
0
                if (dict_find_string(Priv, "StdHW", &ssv) <= 0) {
1322
0
                    *ret = 0;
1323
0
                    break;
1324
0
                }
1325
0
                *ret = (ushort)r_size(ssv);
1326
0
                break;
1327
0
            }
1328
0
        case gs_fapi_font_feature_BlendStemSnapV_count:
1329
0
            {
1330
0
                ref *Priv, *Blend, *bssv, sub;
1331
0
                if (dict_find_string(pdr, "Blend", &Blend) <= 0) {
1332
0
                    *ret = 0;
1333
0
                    break;
1334
0
                }
1335
0
                if (dict_find_string(Blend, "Private", &Priv) <= 0) {
1336
0
                    *ret = 0;
1337
0
                    break;
1338
0
                }
1339
0
                if (dict_find_string(Priv, "StemSnapV", &bssv) <= 0) {
1340
0
                    *ret = 0;
1341
0
                    break;
1342
0
                }
1343
1344
0
                if (array_get(ff->memory, bssv, index, &sub) < 0) {
1345
0
                    *ret = 0;
1346
0
                    break;
1347
0
                }
1348
0
                *ret = (ushort)r_size(&sub);
1349
0
                break;
1350
0
            }
1351
0
        case gs_fapi_font_feature_BlendStemSnapV:
1352
0
            {
1353
0
                ref *Priv, *Blend, *bssv, sub, r;
1354
0
                int aind = 0;
1355
0
                if (dict_find_string(pdr, "Blend", &Blend) <= 0) {
1356
0
                    *ret = 0;
1357
0
                    break;
1358
0
                }
1359
0
                if (dict_find_string(Blend, "Private", &Priv) <= 0) {
1360
0
                    *ret = 0;
1361
0
                    break;
1362
0
                }
1363
0
                if (dict_find_string(Priv, "StemSnapV", &bssv) <= 0) {
1364
0
                    *ret = 0;
1365
0
                    break;
1366
0
                }
1367
1368
0
                while (1) {
1369
0
                    if ((code = array_get(ff->memory, bssv, aind++, &sub)) < 0)
1370
0
                        break;
1371
0
                    if (index - (int)r_size(&sub) < 0) {
1372
0
                        break;
1373
0
                    }
1374
0
                    index -= r_size(&sub);
1375
0
                }
1376
0
                if (code < 0) {
1377
0
                    *ret = 0;
1378
0
                    break;
1379
0
                }
1380
0
                if (array_get(ff->memory, &sub, index, &r) < 0) {
1381
0
                    *ret = 0;
1382
0
                    break;
1383
0
                }
1384
1385
0
                *ret = (ushort)r.value.intval;
1386
0
                break;
1387
0
            }
1388
1389
            /* End MM specifics */
1390
824k
    }
1391
824k
    return code;
1392
824k
}
1393
1394
static int
1395
FAPI_FF_get_long(gs_fapi_font *ff, gs_fapi_font_feature var_id, int index, unsigned long *ret)
1396
27.0k
{
1397
27.0k
    gs_font_type1 *pfont = (gs_font_type1 *) ff->client_font_data;
1398
27.0k
    int code = 0;
1399
1400
27.0k
    ref *pdr = pfont_dict(((gs_font_base *) ff->client_font_data2));
1401
1402
27.0k
    switch ((int)var_id) {
1403
0
        case gs_fapi_font_feature_UniqueID:
1404
0
            *ret = pfont->UID.id;
1405
0
            break;
1406
27.0k
        case gs_fapi_font_feature_BlueScale:
1407
27.0k
            *ret = (ulong) (pfont->data.BlueScale * 65536);
1408
27.0k
            break;
1409
0
        case gs_fapi_font_feature_Subrs_total_size:
1410
0
            {
1411
0
                ref *Private, *Subrs, v;
1412
0
                int lenIV = max(pfont->data.lenIV, 0), k;
1413
0
                ulong size = 0;
1414
0
                long i;
1415
0
                const char *name[2] = { "Subrs", "GlobalSubrs" };
1416
0
                if (dict_find_string(pdr, "Private", &Private) <= 0) {
1417
0
                    *ret = 0;
1418
0
                    break;
1419
0
                }
1420
0
                for (k = 0; k < 2; k++) {
1421
0
                    if (dict_find_string(Private, name[k], &Subrs) > 0)
1422
0
                        for (i = r_size(Subrs) - 1; i >= 0; i--) {
1423
0
                            array_get(pfont->memory, Subrs, i, &v);
1424
0
                            if (r_type(&v) == t_string) {
1425
0
                                size += r_size(&v) - (ff->need_decrypt ? 0 : lenIV);
1426
0
                            }
1427
0
                        }
1428
0
                }
1429
0
                *ret = size;
1430
0
            }
1431
0
            break;
1432
2
        case gs_fapi_font_feature_TT_size:
1433
2
            code = true_type_size(ff->memory, pdr, ret);
1434
2
            break;
1435
27.0k
    }
1436
27.0k
    return code;
1437
27.0k
}
1438
1439
static int
1440
FAPI_FF_get_float(gs_fapi_font *ff, gs_fapi_font_feature var_id, int index, float *ret)
1441
162k
{
1442
162k
    gs_font_type1 *pfont1 = (gs_font_type1 *) ff->client_font_data;
1443
162k
    gs_font_base *pbfont = (gs_font_base *) ff->client_font_data2;
1444
162k
    ref *pdr = pfont_dict(pbfont);
1445
162k
    int code = 0;
1446
162k
    gs_fapi_server *I = pbfont->FAPI;
1447
1448
162k
    switch ((int)var_id) {
1449
162k
        case gs_fapi_font_feature_FontMatrix:
1450
162k
            {
1451
162k
                double FontMatrix_div;
1452
162k
                gs_matrix m, *mptr;
1453
1454
162k
                if (I && I->get_fontmatrix) {
1455
162k
                    FontMatrix_div = 1;
1456
162k
                    mptr = &m;
1457
162k
                    I->get_fontmatrix(I, mptr);
1458
162k
                }
1459
0
                else {
1460
0
                    FontMatrix_div =
1461
0
                        ((ff->is_cid
1462
0
                          && (!FAPI_ISCIDFONT(pbfont))) ? 1000 : 1);
1463
0
                    mptr = &(pbfont->base->FontMatrix);
1464
0
                }
1465
162k
                switch (index) {
1466
27.0k
                    case 0:
1467
27.0k
                    default:
1468
27.0k
                        *ret = (mptr->xx / FontMatrix_div);
1469
27.0k
                        break;
1470
27.0k
                    case 1:
1471
27.0k
                        *ret = (mptr->xy / FontMatrix_div);
1472
27.0k
                        break;
1473
27.0k
                    case 2:
1474
27.0k
                        *ret = (mptr->yx / FontMatrix_div);
1475
27.0k
                        break;
1476
27.0k
                    case 3:
1477
27.0k
                        *ret = (mptr->yy / FontMatrix_div);
1478
27.0k
                        break;
1479
27.0k
                    case 4:
1480
27.0k
                        *ret = (mptr->tx / FontMatrix_div);
1481
27.0k
                        break;
1482
27.0k
                    case 5:
1483
27.0k
                        *ret = (mptr->ty / FontMatrix_div);
1484
27.0k
                        break;
1485
162k
                }
1486
162k
                break;
1487
162k
            }
1488
1489
162k
        case gs_fapi_font_feature_WeightVector:
1490
0
            {
1491
0
                if (index < pfont1->data.WeightVector.count) {
1492
0
                    *ret = pfont1->data.WeightVector.values[index];
1493
0
                }
1494
0
                else {
1495
0
                    *ret = 0;
1496
0
                }
1497
0
            }
1498
0
            break;
1499
0
        case gs_fapi_font_feature_BlendDesignPositionsArrayValue:
1500
0
            {
1501
0
                ref *Info, *Array, SubArray, value;
1502
0
                int array_index = index / 8;
1503
1504
0
                index %= 8;
1505
0
                if (dict_find_string(pdr, "FontInfo", &Info) <= 0) {
1506
0
                    *ret = 0;
1507
0
                    break;
1508
0
                }
1509
0
                if (dict_find_string(Info, "BlendDesignPositions", &Array) <= 0) {
1510
0
                    *ret = 0;
1511
0
                    break;
1512
0
                }
1513
0
                if (array_get(ff->memory, Array, array_index, &SubArray) < 0) {
1514
0
                    *ret = 0;
1515
0
                    break;
1516
0
                }
1517
0
                if (array_get(ff->memory, &SubArray, index, &value) < 0)
1518
0
                    return 0;
1519
0
                if (!r_has_type(&value, t_integer)) {
1520
0
                    if (r_has_type(&value, t_real)) {
1521
0
                        *ret = value.value.realval;
1522
0
                    }
1523
0
                    else
1524
0
                        *ret = 0;
1525
0
                }
1526
0
                else
1527
0
                    *ret = ((float)value.value.intval);
1528
0
            }
1529
0
            break;
1530
0
        case gs_fapi_font_feature_BlendDesignMapArrayValue:
1531
0
            {
1532
0
                ref *Info, *Array, SubArray, SubSubArray, value;
1533
0
                int array_index = index / 64;
1534
1535
0
                index %= 8;
1536
0
                if (dict_find_string(pdr, "FontInfo", &Info) <= 0) {
1537
0
                    *ret = 0;
1538
0
                    break;
1539
0
                 }
1540
0
                if (dict_find_string(Info, "BlendDesignMap", &Array) <= 0) {
1541
0
                    *ret = 0;
1542
0
                    break;
1543
0
                }
1544
0
                if (array_get(ff->memory, Array, array_index, &SubArray) < 0) {
1545
0
                    *ret = 0;
1546
0
                    break;
1547
0
                }
1548
0
                if (array_get(ff->memory, &SubArray, index, &SubSubArray) < 0) {
1549
0
                    *ret = 0;
1550
0
                    break;
1551
0
                }
1552
0
                if (array_get(ff->memory, &SubSubArray, index, &value) < 0) {
1553
0
                    *ret = 0;
1554
0
                    break;
1555
0
                }
1556
0
                if (!r_has_type(&value, t_integer)) {
1557
0
                    if (r_has_type(&value, t_real)) {
1558
0
                        *ret = (value.value.realval);
1559
0
                    }
1560
0
                    else
1561
0
                        *ret = 0;
1562
0
                }
1563
0
                else
1564
0
                    *ret = ((float)value.value.intval);
1565
0
            }
1566
0
            break;
1567
0
        case gs_fapi_font_feature_BlendBlueScale:
1568
0
            {
1569
0
                ref *Priv, *Blend, *bbs, r;
1570
1571
0
                if (dict_find_string(pdr, "Blend", &Blend) <= 0) {
1572
0
                    *ret = 0;
1573
0
                    break;
1574
0
                }
1575
0
                if (dict_find_string(Blend, "Private", &Priv) <= 0) {
1576
0
                    *ret = 0;
1577
0
                    break;
1578
0
                }
1579
0
                if (dict_find_string(Priv, "BlueScale", &bbs) <= 0) {
1580
0
                    *ret = 0;
1581
0
                    break;
1582
0
                }
1583
0
                if (array_get(ff->memory, bbs, index, &r) < 0) {
1584
0
                    *ret = 0;
1585
0
                    break;
1586
0
                }
1587
0
               if (r_has_type(&r, t_real))
1588
0
                   *ret = r.value.realval;
1589
0
               else if (r_has_type(&r, t_integer))
1590
0
                   *ret = (float)r.value.intval;
1591
0
            }
1592
0
            break;
1593
162k
    }
1594
162k
    return code;
1595
162k
}
1596
1597
static int
1598
FAPI_FF_get_name(gs_fapi_font *ff, gs_fapi_font_feature var_id, int index,
1599
                 char *Buffer, int len)
1600
0
{
1601
0
    ref name, string;
1602
0
    ref *pdr = pfont_dict(((gs_font_base *) ff->client_font_data2));
1603
0
    int code = 0;
1604
1605
0
    switch ((int)var_id) {
1606
0
        case gs_fapi_font_feature_BlendAxisTypes:
1607
0
            {
1608
0
                ref *Info, *Axes;
1609
1610
0
                if (dict_find_string(pdr, "FontInfo", &Info) <= 0) {
1611
0
                    code = gs_note_error(gs_error_undefined);
1612
0
                    break;
1613
0
                }
1614
0
                if (dict_find_string(Info, "BlendAxisTypes", &Axes) <= 0) {
1615
0
                    code = gs_note_error(gs_error_undefined);
1616
0
                    break;
1617
0
                }
1618
0
                if (!r_has_type(Axes, t_array)) {
1619
0
                    code = gs_note_error(gs_error_undefined);
1620
0
                    break;
1621
0
                }
1622
0
                if (array_get(ff->memory, Axes, index, &name) < 0) {
1623
0
                    code = gs_note_error(gs_error_undefined);
1624
0
                    break;
1625
0
                }
1626
0
            }
1627
0
    }
1628
0
    if (code >= 0) {
1629
0
        name_string_ref(ff->memory, &name, &string);
1630
0
        if (r_size(&string) < len) {
1631
0
            memcpy(Buffer, string.value.const_bytes, r_size(&string));
1632
0
            Buffer[r_size(&string)] = 0x00;
1633
0
        }
1634
0
        else {
1635
0
            code = gs_note_error(gs_error_unknownerror);
1636
0
        }
1637
0
    }
1638
0
    return code;
1639
0
}
1640
1641
/* NOTE: we checked the type of $Blend at definefont time, so we know it is a
1642
 * procedure and don't need to check it again here
1643
 */
1644
static int
1645
FAPI_FF_get_proc(gs_fapi_font *ff, gs_fapi_font_feature var_id, int index,
1646
                 char *Buffer)
1647
0
{
1648
0
    ref *pdr = pfont_dict(((gs_font_base *) ff->client_font_data2));
1649
0
    char *ptr = Buffer;
1650
0
    int code = 0;
1651
1652
0
    if (!Buffer)
1653
0
        return_error(gs_error_unknownerror);
1654
1655
0
    switch ((int)var_id) {
1656
0
        case gs_fapi_font_feature_DollarBlend:
1657
0
            {
1658
0
                ref *DBlend, Element, string;
1659
0
                int i;
1660
0
                char Buf[32];
1661
1662
0
                if (dict_find_string(pdr, "$Blend", &DBlend) <= 0) {
1663
0
                    code = gs_note_error(gs_error_undefined);
1664
0
                    break;
1665
0
                }
1666
0
                for (i = 0; i < r_size(DBlend); i++) {
1667
0
                    *ptr++ = 0x20;
1668
0
                    if (array_get(ff->memory, DBlend, i, &Element) < 0) {
1669
0
                        code = gs_note_error(gs_error_undefined);
1670
0
                        break;
1671
0
                    }
1672
0
                    switch (r_btype(&Element)) {
1673
0
                        case t_name:
1674
0
                            name_string_ref(ff->memory, &Element, &string);
1675
1676
0
                            strncpy(ptr, (char *)string.value.const_bytes,
1677
0
                                    r_size(&string));
1678
0
                            ptr += r_size(&string);
1679
0
                            break;
1680
0
                        case t_real:
1681
0
                            gs_snprintf(Buf, sizeof(Buf), "%f", Element.value.realval);
1682
0
                            strcpy(ptr, Buf);
1683
0
                            ptr += strlen(Buf);
1684
0
                            break;
1685
0
                        case t_integer:
1686
0
                            gs_snprintf(Buf, sizeof(Buf), "%"PRIpsint, Element.value.intval);
1687
0
                            strcpy(ptr, Buf);
1688
0
                            ptr += strlen(Buf);
1689
0
                            break;
1690
0
                        case t_operator:
1691
0
                            {
1692
0
                                op_def const *op;
1693
1694
0
                                op = op_index_def(r_size(&Element));
1695
0
                                strcpy(ptr, op->oname + 1);
1696
0
                                ptr += strlen(op->oname + 1);
1697
0
                            }
1698
0
                            break;
1699
0
                        default:
1700
0
                            break;
1701
0
                    }
1702
0
                }
1703
0
            }
1704
0
    }
1705
0
    return code < 0 ? code : (ptr - Buffer);
1706
0
}
1707
1708
static inline void
1709
decode_bytes(byte *p, const byte *s, int l, int lenIV)
1710
73.5k
{
1711
73.5k
    ushort state = 4330;
1712
1713
1.41M
    for (; l; s++, l--) {
1714
1.33M
        uchar c = (*s ^ (state >> 8));
1715
1716
1.33M
        state = (*s + state) * crypt_c1 + crypt_c2;
1717
1.33M
        if (lenIV > 0)
1718
294k
            lenIV--;
1719
1.04M
        else {
1720
1.04M
            *p = c;
1721
1.04M
            p++;
1722
1.04M
        }
1723
1.33M
    }
1724
73.5k
}
1725
1726
static int
1727
get_type1_data(gs_fapi_font *ff, const ref *type1string,
1728
               byte *buf, int buf_length)
1729
208k
{
1730
208k
    gs_font_type1 *pfont = (gs_font_type1 *) ff->client_font_data;
1731
208k
    int lenIV = max(pfont->data.lenIV, 0);
1732
208k
    int length = r_size(type1string) - (ff->need_decrypt ? lenIV : 0);
1733
1734
208k
    if (buf != 0) {
1735
73.5k
        int l = min(length, buf_length);        /*safety */
1736
1737
73.5k
        if (ff->need_decrypt && pfont->data.lenIV >= 0)
1738
73.5k
            decode_bytes(buf, type1string->value.const_bytes, l + lenIV,
1739
73.5k
                         lenIV);
1740
0
        else
1741
0
            memcpy(buf, type1string->value.const_bytes, l);
1742
73.5k
    }
1743
208k
    return length;
1744
208k
}
1745
1746
static int
1747
FAPI_FF_get_gsubr(gs_fapi_font *ff, int index, byte *buf, int buf_length)
1748
0
{
1749
0
    ref *pdr = pfont_dict(((gs_font_base *) ff->client_font_data2));
1750
0
    ref *Private, *GlobalSubrs, subr;
1751
1752
0
    if (dict_find_string(pdr, "Private", &Private) <= 0)
1753
0
        return 0;
1754
0
    if (dict_find_string(Private, "GlobalSubrs", &GlobalSubrs) <= 0)
1755
0
        return 0;
1756
0
    if (array_get(ff->memory,
1757
0
                  GlobalSubrs, index, &subr) < 0 || r_type(&subr) != t_string)
1758
0
        return 0;
1759
0
    return (get_type1_data(ff, &subr, buf, buf_length));
1760
0
}
1761
1762
static int
1763
FAPI_FF_get_subr(gs_fapi_font *ff, int index, byte *buf, int buf_length)
1764
203k
{
1765
203k
    ref *pdr = pfont_dict(((gs_font_base *) ff->client_font_data2));
1766
203k
    ref *Private, *Subrs, subr;
1767
1768
203k
    if (dict_find_string(pdr, "Private", &Private) <= 0)
1769
0
        return 0;
1770
203k
    if (dict_find_string(Private, "Subrs", &Subrs) <= 0)
1771
0
        return 0;
1772
203k
    if (array_get(ff->memory, Subrs, index, &subr) < 0
1773
203k
        || r_type(&subr) != t_string)
1774
0
        return 0;
1775
203k
    return (get_type1_data(ff, &subr, buf, buf_length));
1776
203k
}
1777
1778
static int
1779
FAPI_FF_get_raw_subr(gs_fapi_font *ff, int index, byte *buf,
1780
                     int buf_length)
1781
0
{
1782
0
    ref *pdr = pfont_dict(((gs_font_base *) ff->client_font_data2));
1783
0
    ref *Private, *Subrs, subr;
1784
0
    int code = 0;
1785
1786
0
    do {
1787
0
        if (dict_find_string(pdr, "Private", &Private) <= 0) {
1788
0
            code = gs_note_error(gs_error_undefined);
1789
0
            break;
1790
0
        }
1791
0
        if (dict_find_string(Private, "Subrs", &Subrs) <= 0) {
1792
0
            code = gs_note_error(gs_error_undefined);
1793
0
            break;
1794
0
        }
1795
0
        if (array_get(ff->memory, Subrs, index, &subr) < 0) {
1796
0
            code = gs_note_error(gs_error_undefined);
1797
0
            break;
1798
0
        }
1799
0
        if (r_type(&subr) != t_string) {
1800
0
            code = gs_note_error(gs_error_undefined);
1801
0
            break;
1802
0
        }
1803
0
        if (buf && buf_length && buf_length >= r_size(&subr)) {
1804
0
            memcpy(buf, subr.value.const_bytes, r_size(&subr));
1805
0
        }
1806
0
    } while(0);
1807
1808
0
    return code < 0 ? code : r_size(&subr);
1809
0
}
1810
1811
/* FAPI_FF_get_charstring_name() and FAPI_FF_get_charstring()
1812
 *
1813
 * Generally we'd want to use the dictionary content
1814
 * enumeration API rather than dict_index_entry(), but
1815
 * the FAPI interface doesn't enforce sequential accessing
1816
 * of the indices.
1817
 * Setting up enumeration and enumerating through the entries
1818
 * until we reach the requested valid index is a performance
1819
 * hit we don't want to pay.
1820
 *
1821
 * Luckily, the checks we need for invalid CharString contents
1822
 * also handle empty "slots" in the dictionary.
1823
 */
1824
1825
static int
1826
FAPI_FF_get_charstring_name(gs_fapi_font *ff, int index, byte *buf,
1827
                            ushort buf_length)
1828
0
{
1829
0
    int code = 0;
1830
0
    ref *pdr = pfont_dict(((gs_font_base *) ff->client_font_data2));
1831
0
    ref *CharStrings, eltp[2], string;
1832
1833
0
    do {
1834
0
        if (dict_find_string(pdr, "CharStrings", &CharStrings) <= 0) {
1835
0
            code = gs_note_error(gs_error_undefined);
1836
0
            break;
1837
0
        }
1838
0
        if (dict_index_entry(CharStrings, index, eltp) < 0) {
1839
0
            code = gs_note_error(gs_error_undefined);
1840
0
            break;
1841
0
        }
1842
0
        if (r_type(&eltp[0]) != t_name) {
1843
0
            code = gs_note_error(gs_error_undefined);
1844
0
            break;
1845
0
        }
1846
0
        name_string_ref(ff->memory, &eltp[0], &string);
1847
0
        if (r_size(&string) <= buf_length) {
1848
0
            memcpy(buf, string.value.const_bytes, r_size(&string));
1849
0
            buf[r_size(&string)] = 0x00;
1850
0
        }
1851
0
    } while(0);
1852
0
    return code < 0 ? code : r_size(&string);
1853
0
}
1854
1855
static int
1856
FAPI_FF_get_charstring(gs_fapi_font *ff, int index, byte *buf,
1857
                       ushort buf_length)
1858
0
{
1859
0
    int code = 0;
1860
0
    ref *pdr = pfont_dict(((gs_font_base *) ff->client_font_data2));
1861
0
    ref *CharStrings, eltp[2];
1862
1863
0
    do {
1864
0
        if (dict_find_string(pdr, "CharStrings", &CharStrings) <= 0) {
1865
0
            code = gs_note_error(gs_error_undefined);
1866
0
            break;
1867
0
        }
1868
0
        if (dict_index_entry(CharStrings, index, eltp) < 0) {
1869
0
            code = gs_note_error(gs_error_undefined);
1870
0
            break;
1871
0
        }
1872
0
        if (r_type(&eltp[1]) != t_string) {
1873
0
            code = gs_note_error(gs_error_typecheck);
1874
0
            break;
1875
0
        }
1876
0
        if (buf && buf_length && buf_length >= r_size(&eltp[1])) {
1877
0
            memcpy(buf, eltp[1].value.const_bytes, r_size(&eltp[1]));
1878
0
        }
1879
0
    } while(0);
1880
1881
0
    return code < 0 ? code : r_size(&eltp[1]);
1882
0
}
1883
1884
static int
1885
sfnt_get_sfnt_length(ref *pdr, ulong *len)
1886
0
{
1887
0
    int code = 0;
1888
0
    ref *sfnts, sfnt_elem;
1889
0
    const gs_memory_t *mem = dict_mem(pdr->value.pdict);
1890
1891
0
    *len = 0;
1892
0
    if (r_type(pdr) != t_dictionary ||
1893
0
        dict_find_string(pdr, "sfnts", &sfnts) <= 0) {
1894
0
        code = gs_error_invalidfont;
1895
0
    }
1896
0
    else {
1897
0
        if (r_type(sfnts) != t_array && r_type(sfnts) != t_string) {
1898
0
            code = gs_error_invalidfont;
1899
0
        }
1900
0
        else {
1901
0
            if (r_type(sfnts) == t_string) {
1902
0
                *len = r_size(sfnts);
1903
0
            }
1904
0
            else {
1905
0
                int i;
1906
0
                for (i = 0; i < r_size(sfnts); i++) {
1907
0
                    code = array_get(mem, sfnts, i, &sfnt_elem);
1908
0
                    if (code < 0) break;
1909
0
                    *len += r_size(&sfnt_elem);
1910
0
                }
1911
0
            }
1912
0
        }
1913
0
    }
1914
0
    return code;
1915
0
}
1916
1917
static int
1918
sfnt_get_glyph_offset(ref *pdr, gs_font_type42 *pfont42, int index,
1919
                      ulong *offset0)
1920
0
{                               /* Note : TTC is not supported and probably is unuseful for Type 42. */
1921
0
    sfnts_reader r;
1922
0
    int glyf_elem_size = (pfont42->data.indexToLocFormat) ? 4 : 2;
1923
0
    ulong fullsize;
1924
1925
0
    if (index < pfont42->data.trueNumGlyphs) {
1926
0
        sfnts_reader_init(pfont42->memory, &r, pdr);
1927
0
        r.seek(&r, pfont42->data.loca + index * (ulong)glyf_elem_size);
1928
0
        *offset0 =
1929
0
            pfont42->data.glyf + (glyf_elem_size ==
1930
0
                              2 ? r.rword(&r) * 2 : r.rlong(&r));
1931
0
        r.error = sfnt_get_sfnt_length(pdr, &fullsize);
1932
0
        if (r.error < 0 || *offset0 > fullsize) {
1933
0
            r.error = gs_note_error(gs_error_invalidaccess);
1934
0
        }
1935
0
    }
1936
0
    else {
1937
0
        r.error = gs_note_error(gs_error_rangecheck);
1938
0
    }
1939
0
    return (r.error);
1940
0
}
1941
1942
static int
1943
ps_get_GlyphDirectory_data_ptr(gs_fapi_font *ff, int char_code,
1944
                               const byte **ptr)
1945
0
{
1946
0
    ref *pdr = pfont_dict(((gs_font_base *) ff->client_font_data2));
1947
0
    ref *GlyphDirectory, glyph0, *glyph = &glyph0, glyph_index;
1948
1949
0
    if (dict_find_string(pdr, "GlyphDirectory", &GlyphDirectory) > 0) {
1950
0
        if (((r_type(GlyphDirectory) == t_dictionary &&
1951
0
              (make_int(&glyph_index, char_code),
1952
0
               dict_find(GlyphDirectory, &glyph_index, &glyph) > 0)) ||
1953
0
             (r_type(GlyphDirectory) == t_array &&
1954
0
              array_get(ff->memory, GlyphDirectory, char_code, &glyph0) >= 0)
1955
0
            )
1956
0
            && r_type(glyph) == t_string) {
1957
0
            *ptr = glyph->value.const_bytes;
1958
0
            return (r_size(glyph));
1959
0
        }
1960
0
        else
1961
            /* We have a GlyphDirectory, but couldn't find the glyph. If we
1962
             * return -1 then we will attempt to use glyf and loca which
1963
             * will fail. Instead return 0, so we execute an 'empty' glyph.
1964
             */
1965
0
            return 0;
1966
0
    }
1967
0
    return -1;
1968
0
}
1969
1970
static int
1971
get_charstring(gs_fapi_font *ff, int char_code, ref **proc, ref *char_name)
1972
0
{
1973
0
    ref *CharStrings;
1974
0
    ref *pdr = pfont_dict(((gs_font_base *) ff->client_font_data2));
1975
1976
0
    if (ff->is_type1) {
1977
0
        if (ff->is_cid)
1978
0
            return -1;
1979
0
        if (dict_find_string(pdr, "CharStrings", &CharStrings) <= 0)
1980
0
            return -1;
1981
1982
0
        if (ff->char_data != NULL) {
1983
            /*
1984
             * Can't use char_code in this case because hooked Type 1 fonts
1985
             * with 'glyphshow' may render a character which has no
1986
             * Encoding entry.
1987
             */
1988
0
            if (name_ref
1989
0
                (ff->memory, ff->char_data, ff->char_data_len, char_name,
1990
0
                 -1) < 0)
1991
0
                return -1;
1992
0
        }
1993
0
        else {                  /* seac */
1994
0
            i_ctx_t *i_ctx_p = (i_ctx_t *) ff->client_ctx_p;
1995
0
            ref *StandardEncoding;
1996
1997
0
            if (dict_find_string
1998
0
                (systemdict, "StandardEncoding", &StandardEncoding) <= 0
1999
0
                || array_get(ff->memory, StandardEncoding, char_code,
2000
0
                             char_name) < 0) {
2001
0
                if (name_ref
2002
0
                    (ff->memory, (const byte *)".notdef", 7, char_name,
2003
0
                     -1) < 0)
2004
0
                    return -1;
2005
0
            }
2006
0
        }
2007
0
        if (dict_find(CharStrings, char_name, (ref **) proc) <= 0)
2008
0
            return -1;
2009
0
    }
2010
0
    return 0;
2011
0
}
2012
2013
static int
2014
FAPI_FF_get_glyph(gs_fapi_font *ff, gs_glyph char_code, byte *buf, int buf_length)
2015
5.90k
{
2016
    /*
2017
     * We assume that renderer requests glyph data with multiple
2018
     * consecutive calls to this function.
2019
     *
2020
     * For a simple glyph it calls this function exactly twice: first
2021
     * with buf == NULL for requesting the necessary buffer length, and
2022
     * second with buf != NULL for requesting the data (the second call
2023
     * may be skipped if the renderer discontinues the rendering).
2024
     *
2025
     * For a composite glyph it calls this function 2 * (N + 1)
2026
     * times: 2 calls for the main glyph (same as above) followed with
2027
     * 2 * N calls for subglyphs, where N is less or equal to the number
2028
     * of subglyphs (N may be less if the renderer caches glyph data,
2029
     * or discontinues rendering on an exception).
2030
     */
2031
5.90k
    ref *pdr = pfont_dict(((gs_font_base *) ff->client_font_data2));
2032
2033
5.90k
    int glyph_length;
2034
5.90k
    i_ctx_t *i_ctx_p = (i_ctx_t *) ff->client_ctx_p;
2035
2036
5.90k
    if (ff->is_type1) {
2037
5.90k
        if (ff->is_cid) {
2038
0
            const gs_string *char_str = (const gs_string *)ff->char_data;
2039
0
            ref glyph;
2040
2041
0
            make_string(&glyph, avm_foreign | a_readonly, char_str->size,
2042
0
                        char_str->data);
2043
2044
0
            glyph_length = get_type1_data(ff, &glyph, buf, buf_length);
2045
0
        }
2046
5.90k
        else {
2047
5.90k
            ref *CharStrings, *CFFCharStrings, char_name, *glyph;
2048
2049
5.90k
            if (ff->char_data != NULL) {
2050
                /*
2051
                 * Can't use char_code in this case because hooked Type 1 fonts
2052
                 * with 'glyphshow' may render a character which has no
2053
                 * Encoding entry.
2054
                 */
2055
5.90k
                if (name_ref(ff->memory, ff->char_data,
2056
5.90k
                             ff->char_data_len, &char_name, -1) < 0)
2057
0
                    return gs_fapi_glyph_invalid_format;
2058
5.90k
                if (buf != NULL) {
2059
                    /*
2060
                     * Trigger the next call to the 'seac' case below.
2061
                     * Here we use the assumption about call sequence
2062
                     * being documented above.
2063
                     */
2064
5.83k
                    ff->char_data = NULL;
2065
5.83k
                }
2066
5.90k
            }
2067
0
            else {              /* seac */
2068
0
                ref *StandardEncoding;
2069
2070
0
                if (dict_find_string
2071
0
                    (systemdict, "StandardEncoding", &StandardEncoding) <= 0
2072
0
                    || array_get(ff->memory, StandardEncoding, char_code,
2073
0
                                 &char_name) < 0)
2074
0
                    if (name_ref
2075
0
                        (ff->memory, (const byte *)".notdef", 7, &char_name, -1) < 0)
2076
0
                        return gs_fapi_glyph_invalid_format;
2077
0
            }
2078
5.90k
            if (dict_find_string(pdr, "CharStrings", &CharStrings) <= 0)
2079
0
                return gs_fapi_glyph_invalid_format;
2080
2081
5.90k
            if (dict_find(CharStrings, &char_name, &glyph) <= 0) {
2082
0
                if (name_ref
2083
0
                    (ff->memory, (const byte *)".notdef", 7, &char_name, -1) < 0) {
2084
0
                    return gs_fapi_glyph_invalid_format;
2085
0
                }
2086
0
                if (dict_find(CharStrings, &char_name, &glyph) <= 0) {
2087
0
                    return gs_fapi_glyph_invalid_format;
2088
0
                }
2089
0
            }
2090
5.90k
            if (r_has_type(glyph, t_array) || r_has_type(glyph, t_mixedarray))
2091
0
                return gs_fapi_glyph_invalid_format;
2092
2093
5.90k
            if (r_has_type(glyph, t_integer)
2094
5.90k
                && dict_find_string(pdr, "CFFCharStrings", &CFFCharStrings) > 0) {
2095
0
                ref *g2;
2096
0
                if (dict_find(CFFCharStrings, glyph, &g2) <= 0) {
2097
0
                    ref nd;
2098
0
                    make_int(&nd, 0);
2099
0
                    if (dict_find(CFFCharStrings, &nd, &g2) <= 0) {
2100
0
                        return gs_fapi_glyph_invalid_format;
2101
0
                    }
2102
0
                }
2103
0
                glyph = g2;
2104
0
            }
2105
2106
5.90k
            if (!r_has_type(glyph, t_string))
2107
0
                return 0;
2108
5.90k
            glyph_length = get_type1_data(ff, glyph, buf, buf_length);
2109
5.90k
        }
2110
5.90k
    }
2111
0
    else {                      /* type 42 */
2112
0
        const byte *data_ptr;
2113
0
        int l = ff->get_glyphdirectory_data(ff, char_code, &data_ptr);
2114
0
        ref *render_notdef_ref;
2115
0
        bool render_notdef = true;
2116
2117
0
        if (dict_find_string(pdr, ".render_notdef", &render_notdef_ref) > 0
2118
0
            && r_has_type(render_notdef_ref, t_boolean)) {
2119
0
            render_notdef = render_notdef_ref->value.boolval;
2120
0
        }
2121
0
        else {
2122
0
            render_notdef = i_ctx_p->RenderTTNotdef;
2123
0
        }
2124
2125
        /* We should only render the TT notdef if we've been told to - logic lifted from zchar42.c */
2126
0
        if (!render_notdef
2127
0
            &&
2128
0
            ((ff->char_data_len == 7
2129
0
              && strncmp((const char *)ff->char_data, ".notdef", 7) == 0)
2130
0
             || (ff->char_data_len > 9
2131
0
                 && strncmp((const char *)ff->char_data, ".notdef~GS",
2132
0
                            10) == 0))) {
2133
0
            glyph_length = 0;
2134
0
        }
2135
0
        else {
2136
0
            if (l >= 0) {
2137
0
                int MetricsCount = gs_fapi_get_metrics_count(ff), mc =
2138
0
                    MetricsCount << 1;
2139
2140
0
                glyph_length = max((ushort) (l - mc), 0);       /* safety */
2141
0
                if (buf != 0 && glyph_length > 0)
2142
0
                    memcpy(buf, data_ptr + mc,
2143
0
                           min(glyph_length, buf_length) /* safety */ );
2144
0
            }
2145
0
            else {
2146
0
                gs_font_type42 *pfont42 = (gs_font_type42 *) ff->client_font_data;
2147
0
                ulong offset0, length_read;
2148
0
                int error = sfnt_get_glyph_offset(pdr, pfont42, char_code, &offset0);
2149
2150
0
                if (error < 0) {
2151
0
                    glyph_length = gs_fapi_glyph_invalid_index;
2152
0
                }
2153
0
                else if (pfont42->data.len_glyphs) {
2154
0
                    if (char_code <= pfont42->data.numGlyphs)
2155
0
                        glyph_length = pfont42->data.len_glyphs[char_code];
2156
0
                    else
2157
0
                        glyph_length = gs_fapi_glyph_invalid_index;
2158
0
                }
2159
0
                else {
2160
0
                    ulong noffs, endoffs;
2161
                    /* If we haven't got a len_glyphs array, try using the offset of the next glyph offset
2162
                     * to work out the length
2163
                     */
2164
0
                    error = sfnt_get_glyph_offset(pdr, pfont42, char_code + 1, &noffs);
2165
0
                    if (error == 0) {
2166
0
                        glyph_length = noffs - offset0;
2167
0
                        error = sfnt_get_sfnt_length(pdr, &endoffs);
2168
0
                        if (error < 0) {
2169
0
                            glyph_length = gs_fapi_glyph_invalid_index;
2170
0
                        }
2171
0
                        else {
2172
0
                            if (glyph_length + offset0 > endoffs) {
2173
0
                                glyph_length = gs_fapi_glyph_invalid_index;
2174
0
                            }
2175
0
                        }
2176
0
                    }
2177
0
                    else {
2178
                        /* And if we can't get the next glyph offset, use the end of the sfnt data
2179
                         * to work out the length.
2180
                         */
2181
0
                        error = sfnt_get_sfnt_length(pdr, &noffs);
2182
0
                        if (error < 0) {
2183
0
                            glyph_length = gs_fapi_glyph_invalid_index;
2184
0
                        }
2185
0
                        else {
2186
0
                            glyph_length = noffs - offset0;
2187
0
                        }
2188
0
                    }
2189
0
                }
2190
2191
0
                if (buf != 0 && !error) {
2192
0
                    sfnts_reader r;
2193
2194
0
                    sfnts_reader_init(pfont42->memory, &r, pdr);
2195
2196
0
                    r.seek(&r, offset0);
2197
0
                    length_read =
2198
0
                        r.rstring(&r, buf,
2199
0
                                  min(glyph_length,
2200
0
                                      buf_length) /* safety */ );
2201
0
                    if (r.error == 1) {
2202
0
                        glyph_length = gs_fapi_glyph_invalid_index;
2203
0
                    }
2204
                    /* r.error == 2 means a rangecheck, and probably means that the
2205
                     * font is broken, and the final glyph length is longer than the data available for it.
2206
                     * In which case we need to return the number of bytes read.
2207
                     */
2208
0
                    if (r.error == 2) {
2209
0
                        glyph_length = length_read;
2210
0
                    }
2211
0
                }
2212
0
            }
2213
0
        }
2214
0
    }
2215
5.90k
    return glyph_length;
2216
5.90k
}
2217
2218
static int
2219
ps_fapi_get_metrics(gs_fapi_font *ff, gs_string *char_name, gs_glyph cid, double *m, bool vertical)
2220
5.68k
{
2221
5.68k
    ref glyph;
2222
5.68k
    int code;
2223
5.68k
    gs_font_base *pbfont = ((gs_font_base *) ff->client_font_data2);
2224
2225
5.68k
    if (char_name->data != NULL) {
2226
5.68k
        make_string(&glyph, avm_foreign | a_readonly, char_name->size, char_name->data);
2227
5.68k
    }
2228
0
    else {
2229
0
        make_int(&glyph, cid);
2230
0
    }
2231
2232
5.68k
    if (vertical) {
2233
0
        code = zchar_get_metrics2(pbfont, &glyph, m);
2234
0
    }
2235
5.68k
    else {
2236
5.68k
        code = zchar_get_metrics(pbfont, &glyph, m);
2237
5.68k
    }
2238
2239
5.68k
    make_null(&glyph);
2240
2241
5.68k
    return (code);
2242
5.68k
}
2243
2244
2245
/* forward declaration for the ps_ff_stub assignment */
2246
static int ps_get_glyphname_or_cid(gs_text_enum_t *penum,
2247
                                   gs_font_base *pbfont,
2248
                                   gs_string *charstring, gs_string *name,
2249
                                   gs_glyph ccode, gs_string *enc_char_name,
2250
                                   char *font_file_path,
2251
                                   gs_fapi_char_ref *cr, bool bCID);
2252
2253
static int ps_fapi_set_cache(gs_text_enum_t *penum,
2254
                             const gs_font_base *pbfont,
2255
                             const gs_string *char_name, gs_glyph cid,
2256
                             const double pwidth[2], const gs_rect *pbbox,
2257
                             const double Metrics2_sbw_default[4],
2258
                             bool *imagenow);
2259
2260
static const gs_fapi_font ps_ff_stub = {
2261
    0,                          /* server_font_data */
2262
    0,                          /* need_decrypt */
2263
    NULL,                       /* const gs_memory_t */
2264
    0,                          /* font_file_path */
2265
    0,                          /* full_font_buf */
2266
    0,                          /* full_font_buf_len */
2267
    0,                          /* subfont */
2268
    false,                      /* is_type1 */
2269
    false,                      /* is_cid */
2270
    false,                      /* is_outline_font */
2271
    false,                      /* is_mtx_skipped */
2272
    false,                      /* is_vertical */
2273
    false,                      /* metrics_only */
2274
    {{-1, -1}},                 /* ttf_cmap_req */
2275
    {-1, -1},                   /* ttf_cmap_selected */
2276
    0,                          /* client_ctx_p */
2277
    0,                          /* client_font_data */
2278
    0,                          /* client_font_data2 */
2279
    0,                          /* char_data */
2280
    0,                          /* char_data_len */
2281
    0,                          /* embolden */
2282
    FAPI_FF_get_word,
2283
    FAPI_FF_get_long,
2284
    FAPI_FF_get_float,
2285
    FAPI_FF_get_name,
2286
    FAPI_FF_get_proc,
2287
    FAPI_FF_get_gsubr,
2288
    FAPI_FF_get_subr,
2289
    FAPI_FF_get_raw_subr,
2290
    FAPI_FF_get_glyph,
2291
    FAPI_FF_serialize_tt_font,
2292
    NULL,                       /* retrieve_tt_font */
2293
    FAPI_FF_get_charstring,
2294
    FAPI_FF_get_charstring_name,
2295
    ps_get_GlyphDirectory_data_ptr,
2296
    ps_get_glyphname_or_cid,
2297
    ps_fapi_get_metrics,
2298
    ps_fapi_set_cache
2299
};
2300
2301
static int
2302
FAPI_get_xlatmap(i_ctx_t *i_ctx_p, char **xlatmap)
2303
880
{
2304
880
    ref *pref;
2305
880
    int code;
2306
2307
880
    if ((code = dict_find_string(systemdict, ".xlatmap", &pref)) < 0)
2308
0
        return code;
2309
880
    if (code == 0)
2310
0
        return_error(gs_error_undefined);
2311
2312
880
    if (r_type(pref) != t_string)
2313
0
        return_error(gs_error_typecheck);
2314
880
    *xlatmap = (char *)pref->value.bytes;
2315
    /*  Note : this supposes that xlatmap doesn't move in virtual memory.
2316
       Garbager must not be called while plugin executes get_scaled_font, get_decodingID.
2317
       Fix some day with making copy of xlatmap in system memory.
2318
     */
2319
880
    return 0;
2320
880
}
2321
2322
static int
2323
renderer_retcode(gs_memory_t *mem, gs_fapi_server *I, gs_fapi_retcode rc)
2324
0
{
2325
0
    if (rc == 0)
2326
0
        return 0;
2327
0
    emprintf2(mem,
2328
0
              "Error: Font Renderer Plugin ( %s ) return code = %d\n",
2329
0
              I->ig.d->subtype, rc);
2330
0
    return rc < 0 ? rc : gs_error_invalidfont;
2331
0
}
2332
2333
/* <server name>/<null> object .FAPIavailable bool */
2334
static int
2335
zFAPIavailable(i_ctx_t *i_ctx_p)
2336
19.3k
{
2337
19.3k
    os_ptr op = osp;
2338
19.3k
    char *serv_name = NULL;
2339
19.3k
    ref name_ref;
2340
2341
19.3k
    check_op(1);
2342
19.3k
    if (r_has_type(op, t_name)) {
2343
9.66k
        name_string_ref(imemory, op, &name_ref);
2344
2345
9.66k
        serv_name =
2346
9.66k
            (char *) ref_to_string(&name_ref, imemory, "zFAPIavailable");
2347
9.66k
        if (!serv_name) {
2348
0
            return_error(gs_error_VMerror);
2349
0
        }
2350
9.66k
    }
2351
2352
19.3k
    make_bool(op, gs_fapi_available(imemory, serv_name));
2353
2354
19.3k
    if (serv_name) {
2355
9.66k
        gs_free_string(imemory, (byte *) serv_name,
2356
9.66k
                       strlen((char *)serv_name) + 1, "zFAPIavailable");
2357
9.66k
    }
2358
19.3k
    return (0);
2359
19.3k
}
2360
2361
static int
2362
ps_get_server_param(gs_fapi_server *I, const char *subtype, char **server_param, int *server_param_size)
2363
2364
13.5k
{
2365
13.5k
    ref *FAPIconfig, *options, *server_options;
2366
13.5k
    i_ctx_t *i_ctx_p = (i_ctx_t *) I->client_ctx_p;
2367
2368
13.5k
    if (dict_find_string(systemdict, ".FAPIconfig", &FAPIconfig) > 0
2369
13.5k
        && r_has_type(FAPIconfig, t_dictionary)) {
2370
13.5k
        if (dict_find_string(FAPIconfig, "ServerOptions", &options) > 0
2371
13.5k
            && r_has_type(options, t_dictionary)) {
2372
13.5k
            if (dict_find_string(options, (char *)subtype, &server_options) >
2373
13.5k
                0 && r_has_type(server_options, t_string)) {
2374
0
                *server_param = (char *) server_options->value.const_bytes;
2375
0
                *server_param_size = r_size(server_options);
2376
0
            }
2377
13.5k
        }
2378
13.5k
    }
2379
13.5k
    return 1;
2380
13.5k
}
2381
2382
static int
2383
FAPI_refine_font(i_ctx_t *i_ctx_p, os_ptr op, gs_font *pfont,
2384
                 int subfont, const char *font_file_path)
2385
13.5k
{
2386
13.5k
    ref *pdr = op;              /* font dict */
2387
13.5k
    const char *decodingID = NULL;
2388
13.5k
    char *xlatmap = NULL;
2389
13.5k
    gs_font_base *pbfont = (gs_font_base *)pfont;
2390
13.5k
    gs_fapi_server *I = pbfont->FAPI;
2391
13.5k
    ref *Decoding_old;
2392
13.5k
    int code;
2393
2394
13.5k
    if (font_file_path != NULL && pbfont->FAPI_font_data == NULL)
2395
0
        if ((code = FAPI_get_xlatmap(i_ctx_p, &xlatmap)) < 0)
2396
0
            return code;
2397
2398
13.5k
    gs_fapi_set_servers_client_data(imemory, NULL, i_ctx_p);
2399
2400
13.5k
    code =
2401
13.5k
        gs_fapi_prepare_font(pfont, I, subfont, font_file_path,
2402
13.5k
                             NULL, xlatmap, &decodingID);
2403
13.5k
    if (code < 0)
2404
0
        return code;
2405
2406
13.5k
    if (code > 0) {
2407
        /* save refined FontBBox back to PS world */
2408
0
        ref *v, mat[4], arr;
2409
0
        int attrs;
2410
2411
0
        if (dict_find_string(op, "FontBBox", &v) > 0) {
2412
0
            if (!r_has_type(v, t_array) && !r_has_type(v, t_shortarray)
2413
0
                && !r_has_type(v, t_mixedarray))
2414
0
                return_error(gs_error_invalidfont);
2415
0
            make_real(&mat[0], pbfont->FontBBox.p.x);
2416
0
            make_real(&mat[1], pbfont->FontBBox.p.y);
2417
0
            make_real(&mat[2], pbfont->FontBBox.q.x);
2418
0
            make_real(&mat[3], pbfont->FontBBox.q.y);
2419
0
            if (r_has_type(v, t_shortarray) || r_has_type(v, t_mixedarray)
2420
0
                || r_size(v) < 4) {
2421
                /* Create a new full blown array in case the values are reals */
2422
0
                code = ialloc_ref_array(&arr, a_all, 4, "array");
2423
0
                if (code < 0)
2424
0
                    return code;
2425
0
                v = &arr;
2426
0
                code = idict_put_string(op, "FontBBox", &arr);
2427
0
                if (code < 0)
2428
0
                    return code;
2429
0
                ref_assign_new(v->value.refs + 0, &mat[0]);
2430
0
                ref_assign_new(v->value.refs + 1, &mat[1]);
2431
0
                ref_assign_new(v->value.refs + 2, &mat[2]);
2432
0
                ref_assign_new(v->value.refs + 3, &mat[3]);
2433
0
            }
2434
0
            else {
2435
0
                ref_assign_old(v, v->value.refs + 0, &mat[0],
2436
0
                               "FAPI_refine_font_BBox");
2437
0
                ref_assign_old(v, v->value.refs + 1, &mat[1],
2438
0
                               "FAPI_refine_font_BBox");
2439
0
                ref_assign_old(v, v->value.refs + 2, &mat[2],
2440
0
                               "FAPI_refine_font_BBox");
2441
0
                ref_assign_old(v, v->value.refs + 3, &mat[3],
2442
0
                               "FAPI_refine_font_BBox");
2443
0
            }
2444
0
            attrs = v->tas.type_attrs;
2445
0
            r_clear_attrs(v, a_all);
2446
0
            r_set_attrs(v, attrs | a_execute);
2447
0
        }
2448
0
    }
2449
2450
    /* Assign a Decoding : */
2451
13.5k
    if (decodingID != 0 && *decodingID
2452
13.5k
        && dict_find_string(pdr, "Decoding", &Decoding_old) <= 0) {
2453
0
        ref Decoding;
2454
2455
0
        if (FAPI_ISCIDFONT(pbfont)) {
2456
0
            ref *CIDSystemInfo, *Ordering, SubstNWP;
2457
0
            byte buf[30];
2458
0
            int ordering_length, decodingID_length =
2459
0
                min(strlen(decodingID), sizeof(buf) - 2);
2460
2461
0
            if (dict_find_string(pdr, "CIDSystemInfo", &CIDSystemInfo) <= 0
2462
0
                || !r_has_type(CIDSystemInfo, t_dictionary))
2463
0
                return_error(gs_error_invalidfont);
2464
2465
0
            if (dict_find_string(CIDSystemInfo, "Ordering", &Ordering) <= 0
2466
0
                || !r_has_type(Ordering, t_string)) {
2467
0
                return_error(gs_error_invalidfont);
2468
0
            }
2469
2470
0
            ordering_length =
2471
0
                min(r_size(Ordering), sizeof(buf) - 2 - decodingID_length);
2472
0
            memcpy(buf, Ordering->value.const_bytes, ordering_length);
2473
0
            if ((code =
2474
0
                 name_ref(imemory, buf, ordering_length, &SubstNWP, 0)) < 0)
2475
0
                return code;
2476
0
            if ((code =
2477
0
                 dict_put_string(pdr, "SubstNWP", &SubstNWP, NULL)) < 0)
2478
0
                return code;
2479
0
            buf[ordering_length] = '.';
2480
0
            memcpy(buf + ordering_length + 1, decodingID, decodingID_length);
2481
0
            buf[decodingID_length + 1 + ordering_length] = 0;   /* Debug purpose only */
2482
0
            if ((code = name_ref(imemory, buf,
2483
0
                                 decodingID_length + 1 + ordering_length,
2484
0
                                 &Decoding, 0)) < 0)
2485
0
                return code;
2486
0
        }
2487
0
        else if ((code = name_ref(imemory, (const byte *)decodingID,
2488
0
                                  strlen(decodingID), &Decoding, 0)) < 0)
2489
0
            return code;
2490
0
        if ((code = dict_put_string(pdr, "Decoding", &Decoding, NULL)) < 0)
2491
0
            return code;
2492
0
    }
2493
13.5k
    return 0;
2494
13.5k
}
2495
2496
/*  <string|name> <font> <is_disk_font> .rebuildfontFAPI <string|name> <font> */
2497
/*  Rebuild a font for handling it with an external renderer.
2498
2499
    The font was built as a native GS font to allow easy access
2500
    to font features. Then zFAPIrebuildfont sets FAPI entry
2501
    into gx_font_base and replaces BuildGlyph and BuildChar
2502
    to enforce the FAPI handling.
2503
2504
    This operator must not be called with devices which embed fonts.
2505
2506
*/
2507
static int
2508
zFAPIrebuildfont(i_ctx_t *i_ctx_p)
2509
13.5k
{
2510
13.5k
    os_ptr op = osp;
2511
13.5k
    build_proc_refs build;
2512
13.5k
    gs_font *pfont;
2513
13.5k
    int code;
2514
13.5k
    gs_font_base *pbfont;
2515
13.5k
    ref *v;
2516
13.5k
    char *font_file_path = NULL;
2517
13.5k
    char FAPI_ID[20];
2518
13.5k
    const byte *pchars;
2519
13.5k
    uint len;
2520
13.5k
    font_data *pdata;
2521
13.5k
    gs_fapi_server *I;
2522
13.5k
    bool has_buildglyph;
2523
13.5k
    bool has_buildchar;
2524
13.5k
    int subfont;
2525
2526
13.5k
    check_op(3);
2527
13.5k
    code = font_param(op - 1, &pfont);
2528
13.5k
    if (code < 0)
2529
0
        return code;
2530
2531
13.5k
    pbfont = (gs_font_base *) pfont;
2532
2533
13.5k
    check_type(*op, t_boolean);
2534
    /* If someone has copied the font dictionary, we may still
2535
     * have the FAPI entry in the dict, but not have the FAPI
2536
     * server assigned in the font object.
2537
     */
2538
13.5k
    if (pbfont->FAPI == NULL) {
2539
12.6k
        if (dict_find_string(op - 1, "FAPI", &v) <= 0
2540
12.6k
            || !r_has_type(v, t_name))
2541
0
            return_error(gs_error_invalidfont);
2542
12.6k
        obj_string_data(imemory, v, &pchars, &len);
2543
12.6k
        len = min(len, sizeof(FAPI_ID) - 1);
2544
12.6k
        strncpy((char *)FAPI_ID, (const char *)pchars, len);
2545
12.6k
        FAPI_ID[len] = 0;
2546
2547
12.6k
        gs_fapi_set_servers_client_data(imemory, &ps_ff_stub, i_ctx_p);
2548
2549
12.6k
        code =
2550
12.6k
            gs_fapi_find_server(imemory, FAPI_ID,
2551
12.6k
                                (gs_fapi_server **) & (pbfont->FAPI), ps_get_server_param);
2552
12.6k
        if (!pbfont->FAPI || code < 0) {
2553
0
            return_error(gs_error_invalidfont);
2554
0
        }
2555
12.6k
    }
2556
2557
13.5k
    pdata = (font_data *) pfont->client_data;
2558
13.5k
    I = pbfont->FAPI;
2559
2560
13.5k
    if (dict_find_string((op - 1), "SubfontId", &v) > 0
2561
13.5k
        && r_has_type(v, t_integer))
2562
0
        subfont = v->value.intval;
2563
13.5k
    else
2564
13.5k
        subfont = 0;
2565
2566
2567
13.5k
    if (r_type(&(pdata->BuildGlyph)) != t_null) {
2568
13.5k
        has_buildglyph = true;
2569
13.5k
    }
2570
0
    else {
2571
0
        has_buildglyph = false;
2572
0
    }
2573
2574
13.5k
    if (r_type(&(pdata->BuildChar)) != t_null) {
2575
13.5k
        has_buildchar = true;
2576
13.5k
    }
2577
0
    else {
2578
0
        has_buildchar = false;
2579
0
    }
2580
2581
    /* This shouldn't happen, but just in case */
2582
13.5k
    if (has_buildglyph == false && has_buildchar == false) {
2583
0
        has_buildglyph = true;
2584
0
    }
2585
2586
13.5k
    if (dict_find_string(op - 1, "Path", &v) <= 0 || !r_has_type(v, t_string)) {
2587
13.5k
        v = NULL;
2588
13.5k
    }
2589
2590
13.5k
    if (pfont->FontType == ft_CID_encrypted && v == NULL) {
2591
0
        if ((code = build_proc_name_refs(imemory, &build, ".FAPIBuildGlyph9",
2592
0
                                         ".FAPIBuildGlyph9")) < 0) {
2593
0
            return code;
2594
0
        }
2595
0
    }
2596
13.5k
    else {
2597
13.5k
        if ((code = build_proc_name_refs(imemory, &build, ".FAPIBuildChar",
2598
13.5k
                                         ".FAPIBuildGlyph")) < 0) {
2599
0
            return code;
2600
0
        }
2601
13.5k
    }
2602
2603
13.5k
    if (!
2604
13.5k
        ((r_type(&(pdata->BuildChar)) != t_null
2605
13.5k
          && pdata->BuildChar.value.pname && build.BuildChar.value.pname
2606
13.5k
          && name_index(imemory, &pdata->BuildChar) == name_index(imemory,
2607
13.5k
                                                                  &build.
2608
13.5k
                                                                  BuildChar))
2609
13.5k
         || (r_type(&(pdata->BuildGlyph)) != t_null
2610
13.5k
             && pdata->BuildGlyph.value.pname && build.BuildGlyph.value.pname
2611
13.5k
             && name_index(imemory, &pdata->BuildGlyph) == name_index(imemory,
2612
13.5k
                                                                      &build.
2613
13.5k
                                                                      BuildGlyph))))
2614
13.5k
    {
2615
2616
13.5k
        if (has_buildchar == true) {
2617
13.5k
            ref_assign_new(&pdata->BuildChar, &build.BuildChar);
2618
13.5k
        }
2619
0
        else {
2620
0
            make_null(&pdata->BuildChar);
2621
0
        }
2622
2623
13.5k
        if (has_buildglyph == true) {
2624
13.5k
            ref_assign_new(&pdata->BuildGlyph, &build.BuildGlyph);
2625
13.5k
        }
2626
0
        else {
2627
0
            make_null(&pdata->BuildGlyph);
2628
0
        }
2629
13.5k
        if (v != NULL) {
2630
0
            font_file_path =
2631
0
                ref_to_string(v, imemory_global, "font file path");
2632
0
        }
2633
2634
13.5k
        code =
2635
13.5k
            FAPI_refine_font(i_ctx_p, op - 1, pfont, subfont,
2636
13.5k
                             font_file_path);
2637
2638
13.5k
        memcpy(&I->initial_FontMatrix, &pbfont->FontMatrix,
2639
13.5k
               sizeof(gs_matrix));
2640
2641
13.5k
        if (font_file_path != NULL) {
2642
0
            gs_free_string(imemory_global, (byte *) font_file_path,
2643
0
                           r_size(v) + 1, "font file path");
2644
0
        }
2645
13.5k
    }
2646
13.5k
    pop(1);
2647
13.5k
    return code;
2648
13.5k
}
2649
2650
static ulong
2651
array_find(const gs_memory_t *mem, ref *Encoding, ref *char_name)
2652
0
{
2653
0
    ulong n = r_size(Encoding), i;
2654
0
    ref v;
2655
2656
0
    for (i = 0; i < n; i++)
2657
0
        if (array_get(mem, Encoding, i, &v) < 0)
2658
0
            break;
2659
0
        else if (r_type(char_name) == r_type(&v)
2660
0
                 && char_name->value.const_pname == v.value.const_pname)
2661
0
            return i;
2662
0
    return 0;
2663
0
}
2664
2665
static int
2666
zfapi_finish_render(i_ctx_t *i_ctx_p)
2667
0
{
2668
0
    os_ptr op = osp;
2669
0
    gs_font *pfont;
2670
0
    int code = font_param(op - 1, &pfont);
2671
2672
0
    if (code == 0) {
2673
0
        gs_font_base *pbfont = (gs_font_base *) pfont;
2674
0
        gs_fapi_server *I = pbfont->FAPI;
2675
0
        gs_text_enum_t *penum = op_show_find(i_ctx_p);
2676
2677
0
        gs_fapi_set_servers_client_data(imemory, NULL, i_ctx_p);
2678
2679
0
        code = gs_fapi_finish_render(pfont, igs, penum, I);
2680
0
        pop(2);
2681
0
        I->release_char_data(I);
2682
0
    }
2683
0
    return code;
2684
0
}
2685
2686
static int
2687
ps_fapi_set_cache(gs_text_enum_t *penum, const gs_font_base *pbfont,
2688
                  const gs_string *char_name, gs_glyph cid,
2689
                  const double pwidth[2], const gs_rect *pbbox,
2690
                  const double Metrics2_sbw_default[4], bool *imagenow)
2691
5.68k
{
2692
5.68k
    i_ctx_t *i_ctx_p = (i_ctx_t *) pbfont->FAPI->client_ctx_p;
2693
5.68k
    op_proc_t exec_cont = 0;    /* dummy - see below */
2694
5.68k
    int code = 0;
2695
2696
5.68k
    if (cid < GS_MIN_CID_GLYPH) {
2697
5.68k
        ref cname;
2698
2699
5.68k
        make_string(&cname, avm_foreign | a_readonly, char_name->size,
2700
5.68k
                    char_name->data);
2701
5.68k
        code =
2702
5.68k
            zchar_set_cache(i_ctx_p, pbfont, &cname, NULL, pwidth, pbbox,
2703
5.68k
                            zfapi_finish_render, &exec_cont,
2704
5.68k
                            Metrics2_sbw_default);
2705
5.68k
    }
2706
0
    else {
2707
0
        ref cidref;
2708
2709
0
        make_int(&cidref, (cid - GS_MIN_CID_GLYPH));
2710
0
        code = zchar_set_cache(i_ctx_p, pbfont, &cidref, NULL, pwidth, pbbox,
2711
0
                               zfapi_finish_render, &exec_cont,
2712
0
                               Metrics2_sbw_default);
2713
0
    }
2714
2715
5.68k
    if (code >= 0 && exec_cont != NULL) {
2716
5.58k
        *imagenow = true;
2717
5.58k
    }
2718
99
    else {
2719
99
        *imagenow = false;
2720
99
    }
2721
    /* We ignore the value of exec_cont here, and leave it up to
2722
     * gs_fapi_do_char() to do the "right" thing based on the
2723
     * return value
2724
     */
2725
5.68k
    return (code);
2726
5.68k
}
2727
2728
2729
static const byte *
2730
find_substring(const byte *where, int length, const char *what)
2731
0
{
2732
0
    int l = strlen(what);
2733
0
    int n = length - l;
2734
0
    const byte *p = where;
2735
2736
0
    for (; n >= 0; n--, p++)
2737
0
        if (!memcmp(p, what, l))
2738
0
            return p;
2739
0
    return NULL;
2740
0
}
2741
2742
static int
2743
ps_get_glyphname_or_cid(gs_text_enum_t *penum,
2744
                        gs_font_base *pbfont, gs_string *charstring,
2745
                        gs_string *name, gs_glyph ccode,
2746
                        gs_string *enc_char_name, char *font_file_path,
2747
                        gs_fapi_char_ref *cr, bool bCID)
2748
5.68k
{
2749
5.68k
    ref *pdr = pfont_dict(pbfont);
2750
5.68k
    int client_char_code = ccode;
2751
5.68k
    ref char_name, cname_str;
2752
5.68k
    int code = 0;
2753
5.68k
    gs_fapi_server *I = pbfont->FAPI;
2754
5.68k
    bool is_TT_from_type42 = (pbfont->FontType == ft_TrueType && font_file_path == NULL);
2755
5.68k
    bool is_glyph_index = false;
2756
5.68k
    bool is_embedded_type1 =
2757
5.68k
        ((pbfont->FontType == ft_encrypted
2758
5.68k
          || pbfont->FontType == ft_encrypted2) && font_file_path == NULL);
2759
5.68k
    i_ctx_t *i_ctx_p = (i_ctx_t *) I->client_ctx_p;
2760
5.68k
    bool unicode_cp = false;
2761
2762
    /* Obtain the character name : */
2763
5.68k
    if (bCID) {
2764
0
        if (pbfont->FontType == ft_CID_TrueType && font_file_path) {
2765
0
            ref *pdr2, *fidr, *dummy;
2766
0
            pdr2 = pfont_dict(gs_rootfont(igs));
2767
0
            if (dict_find_string(pdr2, "FontInfo", &fidr) > 0 &&
2768
0
                dict_find_string(fidr, "GlyphNames2Unicode", &dummy) > 0)
2769
0
            {
2770
0
                unsigned char uc[4] = {0};
2771
0
                unsigned int cc = 0;
2772
0
                int i, l;
2773
0
                if (penum->text.operation & TEXT_FROM_SINGLE_CHAR) {
2774
0
                    cc = penum->text.data.d_char;
2775
0
                } else if (penum->text.operation & TEXT_FROM_SINGLE_GLYPH) {
2776
0
                    cc = penum->text.data.d_glyph - GS_MIN_CID_GLYPH;
2777
0
                }
2778
0
                else {
2779
0
                    byte *c = (byte *)&penum->text.data.bytes[penum->index - penum->bytes_decoded];
2780
0
                    for (i = 0; i < penum->bytes_decoded ; i++) {
2781
0
                      cc |= c[i] << ((penum->bytes_decoded - 1) - i) * 8;
2782
0
                    }
2783
0
                }
2784
0
                l = ((gs_font_base *)gs_rootfont(igs))->procs.decode_glyph(gs_rootfont(igs), cc + GS_MIN_CID_GLYPH, ccode, (unsigned short *)uc, sizeof(uc));
2785
0
                if (l > 0 && l < sizeof(uc)) {
2786
0
                    cc = 0;
2787
0
                    for (i = 0; i < l; i++) {
2788
0
                        cc |= uc[l - 1 - i] << (i * 8);
2789
0
                    }
2790
0
                    ccode = cc;
2791
0
                    unicode_cp = true;
2792
0
                }
2793
0
            }
2794
0
        }
2795
0
        client_char_code = ccode;
2796
0
        make_null(&char_name);
2797
0
        enc_char_name->data = NULL;
2798
0
        enc_char_name->size = 0;
2799
0
    }
2800
5.68k
    else {
2801
5.68k
        if (ccode != GS_NO_CHAR) {
2802
            /* Translate from PS encoding to char name : */
2803
5.68k
            ref *Encoding;
2804
2805
5.68k
            client_char_code = ccode;
2806
5.68k
            if (dict_find_string(pdr, "Encoding", &Encoding) > 0 &&
2807
5.68k
                (r_has_type(Encoding, t_array) ||
2808
5.68k
                 r_has_type(Encoding, t_shortarray)
2809
5.68k
                 || r_has_type(Encoding, t_mixedarray))) {
2810
5.68k
                if (array_get(imemory, Encoding, client_char_code, &char_name)
2811
5.68k
                    < 0)
2812
0
                    if ((code =
2813
0
                         name_ref(imemory, (const byte *)".notdef", 7,
2814
0
                                  &char_name, -1)) < 0)
2815
0
                        return code;
2816
5.68k
            }
2817
0
            else {
2818
0
                return_error(gs_error_invalidfont);
2819
0
            }
2820
5.68k
        }
2821
0
        else {
2822
0
            code =
2823
0
                names_ref(imemory->gs_lib_ctx->gs_name_table,
2824
0
                          (const byte *)name->data, name->size, &char_name,
2825
0
                          0);
2826
2827
0
        }
2828
        /* We need to store the name as we get it (from the Encoding array), in case it's
2829
         * had the name extended (with "~GS~xx"), we'll remove the extension before passing
2830
         * it to the renderer for a disk based font. But the metrics dictionary may have
2831
         * been constructed using the extended name....
2832
         */
2833
5.68k
        if (!r_has_type(&char_name, t_name))
2834
0
            return_error(gs_error_invalidfont);
2835
5.68k
        name_string_ref(imemory, &char_name, &cname_str);
2836
5.68k
        enc_char_name->data = cname_str.value.bytes;
2837
5.68k
        enc_char_name->size = r_size(&cname_str);
2838
5.68k
    }
2839
2840
    /* Obtain the character code or glyph index : */
2841
5.68k
    cr->char_codes_count = 1;
2842
5.68k
    if (bCID) {
2843
0
        if (font_file_path != NULL) {
2844
0
            ref *Decoding, *TT_cmap = NULL, *SubstNWP;
2845
0
            ref src_type, dst_type;
2846
0
            uint c = 0;
2847
2848
0
            is_glyph_index = true;
2849
2850
0
            if (dict_find_string(pdr, "Decoding", &Decoding) <= 0
2851
0
                || !r_has_type(Decoding, t_dictionary))
2852
0
                return_error(gs_error_invalidfont);
2853
0
            if (dict_find_string(pdr, "SubstNWP", &SubstNWP) <= 0
2854
0
                || !r_has_type(SubstNWP, t_array))
2855
0
                return_error(gs_error_invalidfont);
2856
0
            if (dict_find_string(pdr, "TT_cmap", &TT_cmap) <= 0
2857
0
                || !r_has_type(TT_cmap, t_dictionary)) {
2858
0
                ref *DecodingArray, char_code, char_code1, ih;
2859
0
                int i = client_char_code % 256, n;
2860
2861
0
                make_int(&ih, client_char_code / 256);
2862
                /* Check the Decoding array for this block of CIDs */
2863
0
                if (dict_find(Decoding, &ih, &DecodingArray) <= 0
2864
0
                    || !r_has_type(DecodingArray, t_array)
2865
0
                    || array_get(imemory, DecodingArray, i, &char_code) < 0) {
2866
0
                    return_error(gs_error_invalidfont);
2867
0
                }
2868
2869
                /* Check the Decoding entry */
2870
0
                if (r_has_type(&char_code, t_integer)) {
2871
0
                    n = 1;
2872
0
                }
2873
0
                else if (r_has_type(&char_code, t_array)) {
2874
0
                    DecodingArray = &char_code;
2875
0
                    i = 0;
2876
0
                    n = r_size(DecodingArray);
2877
0
                }
2878
0
                else {
2879
0
                    return_error(gs_error_invalidfont);
2880
0
                }
2881
2882
0
                for (; n--; i++) {
2883
0
                    if (array_get(imemory, DecodingArray, i, &char_code1) < 0
2884
0
                        || !r_has_type(&char_code1, t_integer)) {
2885
0
                        return_error(gs_error_invalidfont);
2886
0
                    }
2887
2888
0
                    c = char_code1.value.intval;
2889
0
                    I->check_cmap_for_GID(I, &c);
2890
0
                    if (c != 0)
2891
0
                        break;
2892
0
                }
2893
0
            }
2894
0
            else {
2895
0
                ref *CIDSystemInfo;
2896
0
                ref *Ordering;
2897
0
                ref *fdict, *CMapDict, *CMapName, *WMode, CMapNameStr;
2898
0
                char *cmapnm = NULL;
2899
0
                int cmapnmlen = 0;
2900
0
                int wmode = 0;
2901
                /* leave off the -H or -V */
2902
0
                const char * const utfcmap = "Identity-UTF16";
2903
0
                int utfcmaplen = strlen(utfcmap);
2904
2905
0
                fdict = pfont_dict(gs_rootfont(igs));
2906
0
                code = dict_find_string(fdict, "CMap", &CMapDict);
2907
0
                if (code > 0 && r_has_type(CMapDict, t_dictionary)) {
2908
0
                    code = dict_find_string(CMapDict, "WMode", &WMode);
2909
0
                    if (code > 0 && r_has_type(WMode, t_integer)) {
2910
0
                        wmode = WMode->value.intval;
2911
0
                    }
2912
0
                    code = dict_find_string(CMapDict, "CMapName", &CMapName);
2913
0
                    if (code > 0 && r_has_type(CMapName, t_name)) {
2914
0
                        name_string_ref(imemory, CMapName, &CMapNameStr);
2915
0
                        cmapnm = (char *)CMapNameStr.value.bytes;
2916
0
                        cmapnmlen = r_size(&CMapNameStr);
2917
0
                    }
2918
0
                }
2919
                /* We only have to lookup the char code if we're *not* using an identity ordering
2920
                   with the exception of Identity-UTF16 which is a different beast altogether */
2921
0
                if (unicode_cp || (cmapnmlen > 0 && !strncmp(cmapnm, utfcmap, cmapnmlen > utfcmaplen ? utfcmaplen : cmapnmlen))
2922
0
                    || (dict_find_string(pdr, "CIDSystemInfo", &CIDSystemInfo) > 0
2923
0
                    && r_has_type(CIDSystemInfo, t_dictionary)
2924
0
                    && dict_find_string(CIDSystemInfo, "Ordering",
2925
0
                                        &Ordering) > 0
2926
0
                    && r_has_type(Ordering, t_string)
2927
0
                    && strncmp((const char *)Ordering->value.bytes,
2928
0
                               "Identity", 8) != 0)) {
2929
2930
0
                    if ((code =
2931
0
                         cid_to_TT_charcode(imemory, Decoding, TT_cmap,
2932
0
                                            SubstNWP, client_char_code, &c,
2933
0
                                            &src_type, &dst_type)) < 0) {
2934
0
                        return code;
2935
0
                    }
2936
0
                }
2937
0
                else {
2938
0
                    if (pbfont->FontType == ft_CID_TrueType) {
2939
0
                        c = ((gs_font_cid2 *)pbfont)->cidata.CIDMap_proc(((gs_font_cid2 *)pbfont),
2940
0
                                                  client_char_code + GS_MIN_CID_GLYPH);
2941
0
                    }
2942
0
                    else {
2943
0
                        c = client_char_code;
2944
0
                    }
2945
0
                }
2946
0
                if (pbfont->FontType == ft_CID_TrueType)
2947
0
                    c = ((gs_font_cid2 *)pbfont)->data.substitute_glyph_index_vertical((gs_font_type42 *)pbfont, c, wmode, ccode);
2948
0
            }
2949
0
            if (pbfont->FontType == ft_CID_TrueType && c == 0 && TT_cmap) {
2950
0
                ref cc32;
2951
0
                ref *gid;
2952
0
                make_int(&cc32, 32);
2953
0
                if (dict_find(TT_cmap, &cc32, &gid) > 0)
2954
0
                    c = gid->value.intval;
2955
0
            }
2956
0
            cr->char_codes[0] = c;
2957
            /* fixme : process the narrow/wide/proportional mapping type,
2958
               using src_type, dst_type. Should adjust the 'matrix' above.
2959
               Call get_font_proportional_feature for proper choice.
2960
             */
2961
0
        }
2962
0
        else {
2963
0
            ref *CIDMap;
2964
0
            byte *Map;
2965
0
            int c_code = client_char_code;
2966
0
            int gdb = 2;
2967
0
            int i;
2968
0
            ref *GDBytes = NULL;
2969
2970
0
            if ((dict_find_string(pdr, "GDBytes", &GDBytes) > 0)
2971
0
                && r_has_type(GDBytes, t_integer)) {
2972
0
                gdb = GDBytes->value.intval;
2973
0
            }
2974
2975
            /* The PDF Reference says that we should use a CIDToGIDMap, but the PDF
2976
             * interpreter converts this into a CIDMap (see pdf_font.ps, processCIDToGIDMap)
2977
             */
2978
0
            if (dict_find_string(pdr, "CIDMap", &CIDMap) > 0
2979
0
                && !r_has_type(CIDMap, t_name) && (r_has_type(CIDMap, t_array)
2980
0
                                                   || r_has_type(CIDMap,
2981
0
                                                                 t_string))) {
2982
2983
0
                if (r_has_type(CIDMap, t_array)) {
2984
2985
                    /* Too big for single string, so its an array of 2 strings */
2986
0
                    code = string_array_access_proc(pbfont->memory, CIDMap, 1,
2987
0
                                                    client_char_code * (ulong)gdb,
2988
0
                                                    gdb, NULL, NULL,
2989
0
                                                    (const byte **)&Map);
2990
0
                }
2991
0
                else {
2992
0
                    if (CIDMap->tas.rsize <= c_code * gdb) {
2993
0
                        c_code = 0;
2994
0
                    }
2995
0
                    Map = &CIDMap->value.bytes[c_code * gdb];
2996
0
                }
2997
0
                cr->char_codes[0] = 0;
2998
0
                is_glyph_index = true;
2999
0
                if (code >= 0) {
3000
0
                    for (i = 0; i < gdb; i++) {
3001
0
                        cr->char_codes[0] = (cr->char_codes[0] << 8) + Map[i];
3002
0
                    }
3003
0
                }
3004
0
                else {
3005
0
                    ref *cstr, *refcode;
3006
0
                    code = dict_find_string(pdr, "CharStrings", &cstr);
3007
0
                    if (code > 0) {
3008
0
                        code = dict_find_string(cstr, ".notdef", &refcode);
3009
0
                        if (code > 0) {
3010
0
                            cr->char_codes[0] = refcode->value.intval;
3011
0
                        }
3012
0
                    }
3013
0
                }
3014
0
            }
3015
0
            else
3016
0
                cr->char_codes[0] = client_char_code;
3017
0
        }
3018
0
    }
3019
5.68k
    else if (is_TT_from_type42) {
3020
        /* This font must not use 'cmap', so compute glyph index from CharStrings : */
3021
0
        ref *CharStrings, *glyph_index, *cmaptab;
3022
3023
0
        if (dict_find_string(pdr, "TT_cmap", &cmaptab) > 0 &&
3024
0
           r_has_type(cmaptab, t_dictionary)) {
3025
0
           const char *nd = ".notdef";
3026
3027
0
           if (enc_char_name->size >= strlen(nd) &&
3028
0
               enc_char_name->data[0] == nd[0] &&
3029
0
               !memcmp(enc_char_name->data, nd, strlen(nd))) {
3030
0
               ref ccref, *gidref, boolref;
3031
0
               make_int(&ccref, ccode);
3032
0
               if (dict_find(cmaptab, &ccref, &gidref) > 0 &&
3033
0
                   r_has_type(gidref, t_integer) &&
3034
0
                   gidref->value.intval == 0) {
3035
0
                   make_bool(&boolref, true);
3036
0
               }
3037
0
               else {
3038
0
                   make_bool(&boolref, false);
3039
0
               }
3040
0
               dict_put_string(pdr, ".render_notdef", &boolref, NULL);
3041
0
           }
3042
0
        }
3043
3044
0
        if (dict_find_string(pdr, "CharStrings", &CharStrings) <= 0
3045
0
            || !r_has_type(CharStrings, t_dictionary))
3046
0
            return_error(gs_error_invalidfont);
3047
0
        if ((dict_find(CharStrings, &char_name, &glyph_index) <= 0)
3048
0
            || r_has_type(glyph_index, t_null)) {
3049
#ifdef DEBUG
3050
            ref *pvalue;
3051
3052
            if (gs_debug_c('1')
3053
                && (dict_find_string(systemdict, "QUIET", &pvalue)) > 0
3054
                && (r_has_type(pvalue, t_boolean)
3055
                    && pvalue->value.boolval == false)) {
3056
                char *glyphn;
3057
3058
                name_string_ref(imemory, &char_name, &char_name);
3059
3060
                glyphn =
3061
                    ref_to_string(&char_name, imemory,
3062
                                  "ps_get_glyphname_or_cid");
3063
                if (glyphn) {
3064
                    dmprintf2(imemory, " Substituting .notdef for %s in the font %s \n",
3065
                             glyphn, pbfont->font_name.chars);
3066
                    gs_free_string(imemory, (byte *) glyphn,
3067
                                   strlen(glyphn) + 1,
3068
                                   "ps_get_glyphname_or_cid");
3069
                }
3070
            }
3071
#endif
3072
3073
0
            cr->char_codes[0] = 0;      /* .notdef */
3074
0
            if ((code =
3075
0
                 name_ref(imemory, (const byte *)".notdef", 7, &char_name,
3076
0
                          -1)) < 0)
3077
0
                return code;
3078
0
        }
3079
0
        else if (r_has_type(glyph_index, t_integer)) {
3080
0
            cr->char_codes[0] = glyph_index->value.intval;
3081
0
        }
3082
0
        else {
3083
0
#if 1                           /* I can't find this ever being used, no idea what it's for..... */
3084
0
            os_ptr op = osp;
3085
3086
            /* Check execution stack has space for BuldChar proc and finish_render */
3087
0
            check_estack(2);
3088
            /* check space and duplicate the glyph index for BuildChar */
3089
0
            check_op(1);
3090
0
            push(1);
3091
0
            ref_assign_inline(op, op - 1);
3092
            /* Come back to fapi_finish_render after running the BuildChar */
3093
0
            push_op_estack(zfapi_finish_render);
3094
0
            ++esp;
3095
0
            ref_assign(esp, glyph_index);
3096
0
            return o_push_estack;
3097
#else
3098
            return (gs_error_invalidfont);
3099
#endif
3100
0
        }
3101
0
        is_glyph_index = true;
3102
0
    }
3103
5.68k
    else if (is_embedded_type1) {
3104
        /*  Since the client passes charstring by callback using I->ff.char_data,
3105
           the client doesn't need to provide a good cr here.
3106
           Perhaps since UFST uses char codes as glyph cache keys (UFST 4.2 cannot use names),
3107
           we provide font char codes equal to document's char codes.
3108
           This trick assumes that Encoding can't point different glyphs
3109
           for same char code. The last should be true due to
3110
           PLRM3, "5.9.4 Subsetting and Incremental Definition of Glyphs".
3111
         */
3112
5.68k
        if (ccode != GS_NO_CHAR) {
3113
5.68k
            cr->char_codes[0] = client_char_code;
3114
5.68k
        }
3115
0
        else {
3116
            /*
3117
             * Reverse Encoding here, because it can be an incremental one.
3118
             * Note that this can cause problems with UFST (see the comment above),
3119
             * if the encoding doesn't contain the glyph name rendered with glyphshow.
3120
             */
3121
0
            ref *Encoding;
3122
0
            ref glyph;
3123
3124
0
            if ((code = name_ref(pbfont->memory, name->data, name->size, &glyph, false)) < 0)
3125
0
                return code;
3126
3127
0
            if (dict_find_string(osp - 1, "Encoding", &Encoding) > 0) {
3128
0
                cr->char_codes[0] =
3129
0
                    (uint) array_find(imemory, Encoding, &glyph);
3130
0
            }
3131
0
            else
3132
0
                return_error(gs_error_invalidfont);
3133
0
        }
3134
5.68k
    }
3135
0
    else {                      /* a non-embedded font, i.e. a disk font */
3136
0
        bool can_retrieve_char_by_name = false;
3137
0
        const byte *p;
3138
3139
0
        obj_string_data(imemory, &char_name, &cr->char_name,
3140
0
                        &cr->char_name_length);
3141
0
        p = find_substring(cr->char_name, cr->char_name_length,
3142
0
                           gx_extendeg_glyph_name_separator);
3143
0
        if (p != NULL) {
3144
0
            cr->char_name_length = p - cr->char_name;
3145
0
            if ((code = name_ref(pbfont->memory, cr->char_name,
3146
0
                             cr->char_name_length, &char_name, true)) < 0)
3147
0
                return code;
3148
0
        }
3149
0
        if ((code =
3150
0
             renderer_retcode(imemory, I,
3151
0
                              I->can_retrieve_char_by_name(I, &I->ff, cr,
3152
0
                                                           &can_retrieve_char_by_name)))
3153
0
            < 0)
3154
0
            return code;
3155
3156
0
        if (!can_retrieve_char_by_name) {
3157
            /* Translate from char name to encoding used with 3d party font technology : */
3158
0
            ref *Decoding, *char_code;
3159
3160
0
            if (dict_find_string(osp - 1, "Decoding", &Decoding) > 0
3161
0
                && r_has_type(Decoding, t_dictionary)) {
3162
0
                if (dict_find(Decoding, &char_name, &char_code) > 0) {
3163
0
                    code = 0;
3164
0
                    if (r_has_type(char_code, t_integer)) {
3165
0
                        int c_code;
3166
0
                        int_param(char_code, 0xFFFF, &c_code);
3167
0
                        cr->char_codes[0] = (gs_glyph)c_code;
3168
0
                    }
3169
0
                    else if (r_has_type(char_code, t_array)
3170
0
                             || r_has_type(char_code, t_shortarray)) {
3171
0
                        int i;
3172
0
                        ref v;
3173
3174
0
                        cr->char_codes_count = r_size(char_code);
3175
0
                        if (cr->char_codes_count > count_of(cr->char_codes))
3176
0
                            code = gs_note_error(gs_error_rangecheck);
3177
0
                        if (code >= 0) {
3178
0
                            for (i = 0; i < cr->char_codes_count; i++) {
3179
0
                                code = array_get(imemory, char_code, i, &v);
3180
0
                                if (code < 0)
3181
0
                                    break;
3182
0
                                if (!r_has_type(char_code, t_integer)) {
3183
0
                                    code = gs_note_error(gs_error_rangecheck);
3184
0
                                    break;
3185
0
                                }
3186
0
                                cr->char_codes[i] = v.value.intval;
3187
0
                            }
3188
0
                        }
3189
0
                    }
3190
0
                    else {
3191
0
                        code = gs_note_error(gs_error_rangecheck);
3192
0
                    }
3193
0
                    if (code < 0) {
3194
0
                        char buf[16];
3195
0
                        int l = cr->char_name_length;
3196
3197
0
                        if (l > sizeof(buf) - 1) {
3198
0
                            l = sizeof(buf) - 1;
3199
0
                        }
3200
0
                        memcpy(buf, cr->char_name, l);
3201
0
                        buf[l] = 0;
3202
0
                        emprintf1(imemory,
3203
0
                                  "Wrong decoding entry for the character '%s'.\n",
3204
0
                                  buf);
3205
0
                        return_error(gs_error_rangecheck);
3206
0
                    }
3207
0
                }
3208
0
            }
3209
0
        }
3210
0
    }
3211
3212
    /* Provide glyph data for renderer : */
3213
    /* Occasionally, char_name is already a glyph index to pass to the rendering engine
3214
     * so don't treat it as a name object.
3215
     * I believe this will only happen with a TTF/Type42, but checking the object type
3216
     * is cheap, and covers all font type eventualities.
3217
     */
3218
5.68k
    if (!I->ff.is_cid && r_has_type(&char_name, t_name)) {
3219
5.68k
        ref sname;
3220
3221
5.68k
        name_string_ref(imemory, &char_name, &sname);
3222
5.68k
        I->ff.char_data = sname.value.const_bytes;
3223
5.68k
        I->ff.char_data_len = r_size(&sname);
3224
5.68k
    }
3225
0
    else if (I->ff.is_type1) {
3226
0
        I->ff.char_data = charstring;
3227
0
    }
3228
3229
5.68k
    cr->is_glyph_index = is_glyph_index;
3230
5.68k
    cr->client_char_code = client_char_code;
3231
3232
5.68k
    return (code);
3233
5.68k
}
3234
3235
3236
static int
3237
FAPI_char(i_ctx_t *i_ctx_p, bool bBuildGlyph, ref *charstring)
3238
5.68k
{                               /* Stack : <font> <code|name> --> - */
3239
5.68k
    os_ptr op = osp;
3240
5.68k
    ref *pdr = op - 1;
3241
5.68k
    ref *v;
3242
5.68k
    char *font_file_path = NULL;
3243
5.68k
    gs_font *pfont;
3244
5.68k
    int code;
3245
3246
5.68k
    check_op(2);
3247
5.68k
    code = font_param(osp - 1, &pfont);
3248
3249
5.68k
    if (code == 0) {
3250
5.68k
        gs_font_base *pbfont = (gs_font_base *) pfont;
3251
5.68k
        bool bCID = (FAPI_ISCIDFONT(pbfont) || charstring != NULL);
3252
5.68k
        int subfont;
3253
5.68k
        gs_fapi_server *I = pbfont->FAPI;
3254
5.68k
        gs_text_enum_t *penum = op_show_find(i_ctx_p);
3255
5.68k
        gs_string char_string, *c_string_p = NULL;
3256
5.68k
        gs_string char_name, *c_name_p = NULL;
3257
5.68k
        gs_glyph cindex = GS_NO_CHAR;
3258
5.68k
        ref gname;
3259
3260
5.68k
        if (I == NULL)
3261
0
            return_error(gs_error_invalidfont);
3262
3263
        /* initialise the FAPI font, this includes language specific stuff */
3264
5.68k
        I->ff = ps_ff_stub;
3265
3266
5.68k
        I->client_ctx_p = i_ctx_p;
3267
3268
5.68k
        if (bBuildGlyph && !bCID) {
3269
0
            if (r_type(op) != t_name) {
3270
0
                name_enter_string(imemory, ".notdef", op);
3271
0
            }
3272
0
            check_type(*op, t_name);
3273
3274
0
            name_string_ref(imemory, op, &gname);
3275
0
            c_name_p = &char_name;
3276
0
            c_name_p->data = gname.value.bytes;
3277
0
            c_name_p->size = r_size(&gname);
3278
3279
0
        }
3280
5.68k
        else {
3281
5.68k
            int chint;
3282
5.68k
            if (bBuildGlyph && pbfont->FontType == ft_CID_TrueType
3283
5.68k
                && r_has_type(op, t_name)) {
3284
0
                ref *chstrs, *chs;
3285
3286
                /* This logic is lifted from %Type11BuildGlyph in gs_cidfn.ps
3287
                 * Note we only have to deal with mistakenly being given a name object
3288
                 * here, the out of range CID is handled later
3289
                 */
3290
0
                if ((dict_find_string(op - 1, "CharStrings", &chstrs)) <= 0) {
3291
0
                    return_error(gs_error_undefined);
3292
0
                }
3293
3294
0
                if ((dict_find_string(chstrs, ".notdef", &chs)) <= 0) {
3295
0
                    return_error(gs_error_undefined);
3296
0
                }
3297
0
                ref_assign_inline(op, chs);
3298
0
            }
3299
3300
5.68k
            make_null(&gname);
3301
5.68k
            check_type(*op, t_integer);
3302
5.68k
            int_param(op, 0xFFFF, (int *)&chint);
3303
5.68k
            cindex = chint;
3304
5.68k
        }
3305
3306
5.68k
        if (dict_find_string(pdr, "SubfontId", &v) > 0
3307
5.68k
            && r_has_type(v, t_integer))
3308
0
            subfont = v->value.intval;
3309
5.68k
        else
3310
5.68k
            subfont = 0;
3311
3312
5.68k
        if (dict_find_string(osp - 1, "Path", &v) > 0
3313
5.68k
            && r_has_type(v, t_string)) {
3314
0
            font_file_path = ref_to_string(v, imemory, "font file path");
3315
0
        }
3316
3317
5.68k
        if (charstring) {
3318
0
            c_string_p = &char_string;
3319
0
            c_string_p->data = charstring->value.bytes;
3320
0
            c_string_p->size = r_size(charstring);
3321
0
        }
3322
3323
5.68k
        code =
3324
5.68k
            gs_fapi_do_char(pfont, igs, penum, font_file_path,
3325
5.68k
                            bBuildGlyph, c_string_p, c_name_p, (gs_char)cindex, cindex,
3326
5.68k
                            subfont);
3327
5.68k
        if (font_file_path != NULL) {
3328
0
            gs_free_string(imemory, (byte *) font_file_path, r_size(v) + 1,
3329
0
                           "font file path");
3330
0
        }
3331
        /* This handles the situation where a charstring has been replaced with a PS procedure.
3332
         * against the rules, but not *that* rare.
3333
         * It's also something that GS does internally to simulate font styles.
3334
         */
3335
5.68k
        if (code == gs_error_unregistered) {
3336
0
            os_ptr op = osp;
3337
0
            ref *proc = NULL, gname;
3338
3339
0
            if (I->ff.is_type1
3340
0
                && (get_charstring(&I->ff, cindex, &proc, &gname) >= 0)
3341
0
                && proc != NULL && (r_has_type(proc, t_array)
3342
0
                    || r_has_type(proc, t_mixedarray))) {
3343
0
                push(2);
3344
0
                ref_assign(op - 1, &gname);
3345
0
                ref_assign(op, proc);
3346
0
                return (zchar_exec_char_proc(i_ctx_p));
3347
0
            }
3348
0
            else {
3349
0
                return_error(gs_error_invalidfont);
3350
0
            }
3351
0
        }
3352
5.68k
    }
3353
    /* We've already imaged teh glyph, pop the operands */
3354
5.68k
    if (code == 0)
3355
5.58k
        pop(2);
3356
5.68k
    return code;
3357
5.68k
}
3358
3359
static int
3360
zFAPIBuildGlyph9(i_ctx_t *i_ctx_p)
3361
0
{
3362
    /*  The alghorithm is taken from %Type9BuildGlyph - see gs_cidfn.ps .  */
3363
0
    os_ptr lop, op = osp;
3364
0
    int cid, code;
3365
0
    avm_space s = ialloc_space(idmemory);
3366
0
    ref font9 = *pfont_dict(gs_currentfont(igs));
3367
0
    ref *rFDArray, f;
3368
0
    int font_index;
3369
3370
0
    check_op(2);
3371
0
    check_type(op[0], t_integer);
3372
0
    check_type(op[-1], t_dictionary);
3373
0
    cid = op[0].value.intval;
3374
0
    push(2);
3375
0
    op[-1] = *pfont_dict(gs_currentfont(igs));
3376
0
    op[0] = op[-2];             /* <font0> <cid> <font9> <cid> */
3377
0
    ialloc_set_space(idmemory, (r_is_local(op - 3) ? avm_global : avm_local));  /* for ztype9mapcid */
3378
3379
    /* stack: <font0> <cid> <font9> <cid> */
3380
0
    if ((code = ztype9mapcid(i_ctx_p)) < 0)
3381
0
        return code;            /* <font0> <cid> <charstring> <font_index> */
3382
    /* fixme: what happens if the charstring is absent ?
3383
       Can FDArray contain 'null' (see %Type9BuildGlyph in gs_cidfn.ps)? */
3384
0
    font_index = op[0].value.intval;
3385
0
    if (dict_find_string(&font9, "FDArray", &rFDArray) <= 0
3386
0
        || r_type(rFDArray) != t_array)
3387
0
        return_error(gs_error_invalidfont);
3388
0
    if (array_get(imemory, rFDArray, font_index, &f) < 0
3389
0
        || r_type(&f) != t_dictionary)
3390
0
        return_error(gs_error_invalidfont);
3391
3392
0
    op[0] = op[-2];
3393
0
    op[-2] = op[-1];            /* Keep the charstring on ostack for the garbager. */
3394
0
    op[-1] = f;                 /* <font0> <charstring> <subfont> <cid> */
3395
0
    if ((code = FAPI_char(i_ctx_p, true, op - 2)) < 0)
3396
0
        return code;
3397
    /* stack: <font0> <charstring> */
3398
3399
0
    lop = osp;
3400
0
    if (code == 5) {
3401
0
        int i, ind = (lop - op);
3402
3403
0
        op = osp;
3404
3405
0
        for (i = ind; i >= 0; i--) {
3406
0
            op[-i - 2] = op[-i];
3407
0
        }
3408
0
        pop(2);
3409
0
    }
3410
0
    else if (code < 0) {        /* <font0> <dirty> <dirty> <dirty> */
3411
        /* Adjust ostack for the correct error handling : */
3412
0
        make_int(op - 2, cid);
3413
0
        pop(2);                 /* <font0> <cid> */
3414
0
    }
3415
0
    else if (code != 5) {       /* <font0> <dirty> */
3416
3417
3418
0
        pop(2);                 /* */
3419
        /*  Note that this releases the charstring, and it may be garbage-collected
3420
           before the interpreter calls fapi_finish_render. This requires the server
3421
           to keep glyph raster internally between calls to get_char_raster_metrics
3422
           and get_char_raster. Perhaps UFST cannot provide metrics without
3423
           building a raster, so this constraint actually goes from UFST.
3424
         */
3425
0
    }
3426
0
    ialloc_set_space(idmemory, s);
3427
0
    return code;
3428
0
}
3429
3430
/* <font> <code> .FAPIBuildChar - */
3431
static int
3432
zFAPIBuildChar(i_ctx_t *i_ctx_p)
3433
5.68k
{
3434
5.68k
    return FAPI_char(i_ctx_p, false, NULL);
3435
5.68k
}
3436
3437
/* non-CID : <font> <code> .FAPIBuildGlyph - */
3438
/*     CID : <font> <name> .FAPIBuildGlyph - */
3439
static int
3440
zFAPIBuildGlyph(i_ctx_t *i_ctx_p)
3441
0
{
3442
0
    return FAPI_char(i_ctx_p, true, NULL);
3443
0
}
3444
3445
3446
/* <font_dict> .FAPIpassfont bool <font_dict> */
3447
/* must insert /FAPI to font dictionary */
3448
static int
3449
zFAPIpassfont(i_ctx_t *i_ctx_p)
3450
880
{
3451
880
    os_ptr op = osp;
3452
880
    gs_font *pfont;
3453
880
    int code;
3454
880
    char *font_file_path = NULL;
3455
880
    ref *v;
3456
880
    char *xlatmap = NULL;
3457
880
    char *fapi_request = NULL;
3458
880
    char *fapi_id = NULL;
3459
880
    ref reqstr;
3460
880
    int subfont;
3461
3462
880
    check_op(1);
3463
    /* Normally embedded fonts have no Path, but if a CID font is
3464
     * emulated with a TT font, and it is hooked with FAPI,
3465
     * the path presents and is neccessary to access the full font data.
3466
     */
3467
880
    check_type(*op, t_dictionary);
3468
3469
880
    code = font_param(osp, &pfont);
3470
880
    if (code < 0)
3471
0
        return code;
3472
3473
880
    if (dict_find_string(op, "SubfontId", &v) > 0
3474
880
        && r_has_type(v, t_integer))
3475
0
        subfont = v->value.intval;
3476
880
    else
3477
880
        subfont = 0;
3478
3479
880
    code = FAPI_get_xlatmap(i_ctx_p, &xlatmap); /* Useful for emulated fonts hooked with FAPI. */
3480
880
    if (code < 0)
3481
0
        return code;
3482
3483
    /* If the font dictionary contains a FAPIPlugInReq key, the the PS world wants us
3484
     * to try to use a specific FAPI plugin, so find it, and try it....
3485
     */
3486
880
    if (dict_find_string(op, "FAPIPlugInReq", &v) > 0 && r_type(v) == t_name) {
3487
3488
0
        name_string_ref(imemory, v, &reqstr);
3489
3490
0
        fapi_request = ref_to_string(&reqstr, imemory, "zFAPIpassfont");
3491
0
    }
3492
3493
880
    if (dict_find_string(op, "Path", &v) > 0 && r_has_type(v, t_string))
3494
0
        font_file_path = ref_to_string(v, imemory_global, "font file path");
3495
3496
880
    gs_fapi_set_servers_client_data(imemory, &ps_ff_stub, i_ctx_p);
3497
3498
880
    code =
3499
880
        gs_fapi_passfont(pfont, subfont, font_file_path, NULL, fapi_request, xlatmap,
3500
880
                         &fapi_id, NULL, ps_get_server_param);
3501
3502
880
    if (font_file_path != NULL)
3503
0
        gs_free_string(imemory_global, (byte *) font_file_path, r_size(v) + 1,
3504
880
                       "font file path");
3505
3506
880
    if (fapi_request != NULL)
3507
0
        gs_free_string(imemory, (byte *) fapi_request,
3508
880
                       strlen(fapi_request) + 1, "do_FAPIpassfont");
3509
880
    if (code < 0 && code != gs_error_invalidaccess)
3510
1
        return code;
3511
3512
879
    if (code >= 0 && fapi_id != NULL) {
3513
879
        ref FAPI_ID;
3514
3515
879
        if ((code =
3516
879
             name_ref(imemory, (const byte *)fapi_id,
3517
879
                      strlen(fapi_id), &FAPI_ID, false)) < 0)
3518
0
            return code;
3519
879
        if ((code = dict_put_string(op, "FAPI", &FAPI_ID, NULL)) < 0)
3520
0
            return code;        /* Insert FAPI entry to font dictionary. */
3521
879
    }
3522
879
    push(1);
3523
879
    make_bool(op, (fapi_id != NULL));
3524
879
    return 0;
3525
879
}
3526
3527
const op_def zfapi_op_defs[] = {
3528
    {"1.FAPIavailable", zFAPIavailable},
3529
    {"2.FAPIpassfont", zFAPIpassfont},
3530
    {"2.FAPIrebuildfont", zFAPIrebuildfont},
3531
    {"2.FAPIBuildChar", zFAPIBuildChar},
3532
    {"2.FAPIBuildGlyph", zFAPIBuildGlyph},
3533
    {"2.FAPIBuildGlyph9", zFAPIBuildGlyph9},
3534
    op_def_end(0)
3535
};