Coverage Report

Created: 2022-10-31 07:00

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