Coverage Report

Created: 2026-04-01 07:17

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ghostpdl/pcl/pl/plfapi.c
Line
Count
Source
1
/* Copyright (C) 2001-2025 Artifex Software, Inc.
2
   All Rights Reserved.
3
4
   This software is provided AS-IS with no warranty, either express or
5
   implied.
6
7
   This software is distributed under license and may not be copied,
8
   modified or distributed except as expressly authorized under the terms
9
   of the license contained in the file LICENSE in this distribution.
10
11
   Refer to licensing information at http://www.artifex.com or contact
12
   Artifex Software, Inc.,  39 Mesa Street, Suite 108A, San Francisco,
13
   CA 94129, USA, for further information.
14
*/
15
16
/* Font API support  */
17
18
#include "memory_.h"
19
#include "gsmemory.h"
20
#include "gserrors.h"
21
#include "gxdevice.h"
22
#include "gxfont.h"
23
#include "gzstate.h"
24
#include "gxchar.h"             /* for st_gs_show_enum */
25
#include "gdebug.h"
26
#include "gxfapi.h"
27
#include "gscoord.h"
28
#include "gsimage.h"            /* for gs_image_enum for plchar.h */
29
#include "gspath.h"
30
31
#include "plfont.h"
32
#include "plchar.h"
33
#include "plfapi.h"
34
35
/* defaults for locations of font collection objects (fco's) and
36
   plugins the root data directory.  These are internally separated with
37
   ':' but environment variable use the gp separator */
38
39
#ifndef UFSTFONTDIR
40
#if 0
41
static const char *UFSTFONTDIR = "/usr/local/fontdata5.0/";     /* A bogus linux location */
42
#endif
43
static const char *UFSTFONTDIR = "";    /* A bogus linux location */
44
#endif
45
46
/* default list of fcos and plugins - relative to UFSTFONTDIR */
47
/* FIXME: better solution for file name list separators */
48
#ifndef __WIN32__
49
static const char *UFSTFCOS =
50
    "%rom%fontdata/mtfonts/pclps2/mt3/pclp2_xj.fco:%rom%fontdata/mtfonts/pcl45/mt3/wd____xh.fco";
51
#else
52
static const char *UFSTFCOS =
53
    "%rom%fontdata/mtfonts/pclps2/mt3/pclp2_xj.fco;%rom%fontdata/mtfonts/pcl45/mt3/wd____xh.fco";
54
#endif
55
56
static const char *UFSTPLUGINS =
57
    "%rom%fontdata/mtfonts/pcl45/mt3/plug__xi.fco";
58
59
static const char *UFSTDIRPARM = "UFST_SSdir=";
60
61
static const char *UFSTPLUGINPARM = "UFST_PlugIn=";
62
63
extern const char gp_file_name_list_separator;
64
65
/* forward declarations for the pl_ff_stub definition */
66
static int
67
pl_fapi_get_long(gs_fapi_font * ff, gs_fapi_font_feature var_id, int index, unsigned long *ret);
68
69
static int
70
pl_fapi_get_cid(gs_text_enum_t *penum, gs_font_base * pbfont, gs_string * charstring,
71
                gs_string * name, gs_glyph ccode, gs_string * enc_char_name,
72
                char *font_file_path, gs_fapi_char_ref * cr, bool bCID);
73
74
static int
75
pl_fapi_get_glyph(gs_fapi_font * ff, gs_glyph char_code, byte * buf, int buf_length);
76
77
static int
78
pl_fapi_serialize_tt_font(gs_fapi_font * ff, void *buf, int buf_size);
79
80
static int
81
pl_get_glyphdirectory_data(gs_fapi_font * ff, int char_code,
82
                           const byte ** ptr);
83
84
static int
85
pl_fapi_set_cache(gs_text_enum_t * penum, const gs_font_base * pbfont,
86
                  const gs_string * char_name, gs_glyph cid,
87
                  const double pwidth[2], const gs_rect * pbbox,
88
                  const double Metrics2_sbw_default[4], bool * imagenow);
89
90
static int
91
pl_fapi_get_metrics(gs_fapi_font * ff, gs_string * char_name, gs_glyph cid,
92
                    double *m, bool vertical);
93
94
static const gs_fapi_font pl_ff_stub = {
95
    0,                          /* server_font_data */
96
    0,                          /* need_decrypt */
97
    NULL,                       /* const gs_memory_t */
98
    0,                          /* font_file_path */
99
    0,                          /* full_font_buf */
100
    0,                          /* full_font_buf_len */
101
    0,                          /* subfont */
102
    false,                      /* is_type1 */
103
    false,                      /* is_cid */
104
    false,                      /* is_outline_font */
105
    false,                      /* is_mtx_skipped */
106
    false,                      /* is_vertical */
107
    false,                      /* metrics_only */
108
    {{3, 10}, {3, 1}, {-1, -1}, {-1, -1}, {-1, -1}},    /* ttf_cmap_req */
109
    {-1 , -1},                                          /* ttf_cmap_selected */
110
    0,                          /* client_ctx_p */
111
    0,                          /* client_font_data */
112
    0,                          /* client_font_data2 */
113
    0,                          /* char_data */
114
    0,                          /* char_data_len */
115
    0,                          /* embolden */
116
    NULL,                       /* get_word */
117
    pl_fapi_get_long,           /* get_long */
118
    NULL,                       /* get_float */
119
    NULL,                       /* get_name */
120
    NULL,                       /* get_proc */
121
    NULL,                       /* get_gsubr */
122
    NULL,                       /* get_subr */
123
    NULL,                       /* get_raw_subr */
124
    pl_fapi_get_glyph,          /* get_glyph */
125
    pl_fapi_serialize_tt_font,  /* serialize_tt_font */
126
    NULL,                       /* retrieve_tt_font */
127
    NULL,                       /* get_charstring */
128
    NULL,                       /* get_charstring_name */
129
    pl_get_glyphdirectory_data, /* get_GlyphDirectory_data_ptr */
130
    pl_fapi_get_cid,            /* get_glyphname_or_cid */
131
    pl_fapi_get_metrics,        /* fapi_get_metrics */
132
    pl_fapi_set_cache           /* fapi_set_cache */
133
};
134
135
static int
136
pl_fapi_get_long(gs_fapi_font * ff, gs_fapi_font_feature var_id, int index, unsigned long *ret)
137
63
{
138
63
    gs_font *pfont = (gs_font *) ff->client_font_data;
139
63
    pl_font_t *plfont = (pl_font_t *) pfont->client_data;
140
63
    int code = 0;
141
63
    (void)index;
142
143
63
    if (var_id == gs_fapi_font_feature_TT_size) {
144
63
        *ret = plfont->header_size - (plfont->offsets.GT +
145
63
                                   (plfont->large_sizes ? 6 : 4));
146
63
    }
147
0
    else {
148
0
        *ret = 0;
149
0
        code = gs_note_error(gs_error_undefined);
150
0
    }
151
63
    return code;
152
63
}
153
154
static int
155
pl_fapi_get_cid(gs_text_enum_t *penum, gs_font_base * pbfont, gs_string * charstring,
156
                gs_string * name, gs_glyph ccode, gs_string * enc_char_name,
157
                char *font_file_path, gs_fapi_char_ref * cr, bool bCID)
158
2.71M
{
159
2.71M
    pl_font_t *plfont = pbfont->client_data;
160
2.71M
    gs_glyph vertical, index = ccode;
161
2.71M
    (void)charstring;
162
2.71M
    (void)name;
163
2.71M
    (void)enc_char_name;
164
2.71M
    (void)font_file_path;
165
2.71M
    (void)bCID;
166
2.71M
    (void)penum;
167
168
2.71M
    if (plfont->allow_vertical_substitutes) {
169
0
        vertical = pl_font_vertical_glyph(ccode, plfont);
170
171
0
        if (vertical != GS_NO_GLYPH)
172
0
            index = vertical;
173
0
    }
174
2.71M
    cr->char_codes[0] = index;
175
2.71M
    return (0);
176
2.71M
}
177
178
static int
179
pl_fapi_get_glyph(gs_fapi_font * ff, gs_glyph char_code, byte * buf, int buf_length)
180
227
{
181
227
    gs_font *pfont = (gs_font *) ff->client_font_data;
182
    /* Zero is a valid size for a TTF glyph, so init to that.
183
     */
184
227
    int size = 0;
185
227
    gs_glyph_data_t pdata;
186
187
227
    if (pl_tt_get_outline((gs_font_type42 *) pfont, char_code, &pdata) == 0) {
188
227
        size = pdata.bits.size;
189
190
227
        if (buf && buf_length >= size) {
191
175
            memcpy(buf, pdata.bits.data, size);
192
175
        }
193
227
    }
194
195
227
    return (size);
196
227
}
197
198
static int
199
pl_fapi_serialize_tt_font(gs_fapi_font * ff, void *buf, int buf_size)
200
63
{
201
63
    gs_font *pfont = (gs_font *) ff->client_font_data;
202
63
    pl_font_t *plfont = (pl_font_t *) pfont->client_data;
203
63
    int code = -1;
204
63
    int offset = (plfont->offsets.GT + (plfont->large_sizes ? 6 : 4));
205
206
63
    if (buf_size >= (plfont->header_size - offset)) {
207
63
        code = 0;
208
209
63
        memcpy(buf, (plfont->header + offset), buf_size);
210
63
    }
211
63
    return (code);
212
63
}
213
214
static int
215
pl_get_glyphdirectory_data(gs_fapi_font * ff, int char_code,
216
                           const byte ** ptr)
217
0
{
218
0
    return (0);
219
0
}
220
221
static int
222
pl_fapi_get_metrics(gs_fapi_font * ff, gs_string * char_name, gs_glyph cid,
223
                    double *m, bool vertical)
224
2.71M
{
225
2.71M
    gs_font_base *pfont = (gs_font_base *) ff->client_font_data;
226
2.71M
    int code = 0;
227
228
    /* We only want to supply metrics for Format 1 Class 2 glyph data (with their
229
     * PCL/PXL specific LSB and width metrics), all the others we leave the
230
     * scaler/render to use the metrics directly from the font/glyph.
231
     */
232
2.71M
    if (pfont->FontType == ft_TrueType) {
233
2.71M
        float sbw[4];
234
235
2.71M
        code = pl_tt_f1c2_get_metrics((gs_font_type42 *)pfont, cid, pfont->WMode & 1, sbw);
236
2.71M
        if (code == 0) {
237
0
            m[0] = sbw[0];
238
0
            m[1] = sbw[1];
239
0
            m[2] = sbw[2];
240
0
            m[3] = sbw[3];
241
0
            code = 2;
242
0
        }
243
2.71M
        else
244
2.71M
            code = 0;
245
2.71M
    }
246
2.71M
    return code;
247
2.71M
}
248
249
static int
250
pl_fapi_set_cache(gs_text_enum_t * penum, const gs_font_base * pbfont,
251
                  const gs_string * char_name, gs_glyph cid,
252
                  const double pwidth[2], const gs_rect * pbbox,
253
                  const double Metrics2_sbw_default[4], bool * imagenow)
254
1.19M
{
255
1.19M
    gs_gstate *pgs = penum->pgs;
256
1.19M
    float w2[6];
257
1.19M
    int code = 0;
258
1.19M
    gs_fapi_server *I = pbfont->FAPI;
259
260
1.19M
    if ((penum->text.operation & TEXT_DO_DRAW) && (pbfont->WMode & 1)
261
0
        && pwidth[0] == 1.0) {
262
0
        gs_rect tmp_pbbox;
263
0
        gs_matrix save_ctm;
264
0
        const gs_matrix id_ctm = { 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 };
265
        /* This is kind of messy, but the cache entry has already been calculated
266
           using the in-force matrix. The problem is that we have to call gs_setcachedevice
267
           with the in-force matrix, not the rotated one, so we have to recalculate the extents
268
           to be correct for the rotated glyph.
269
         */
270
271
        /* save the ctm */
272
0
        gs_currentmatrix(pgs, &save_ctm);
273
0
        gs_setmatrix(pgs, &id_ctm);
274
275
        /* magic numbers - we don't completelely understand
276
           the translation magic used by HP.  This provides a
277
           good approximation */
278
0
        gs_translate(pgs, 1.0 / 1.15, -(1.0 - 1.0 / 1.15));
279
0
        gs_rotate(pgs, 90);
280
281
0
        gs_transform(pgs, pbbox->p.x, pbbox->p.y, &tmp_pbbox.p);
282
0
        gs_transform(pgs, pbbox->q.x, pbbox->q.y, &tmp_pbbox.q);
283
284
0
        w2[0] = pwidth[0];
285
0
        w2[1] = pwidth[1];
286
0
        w2[2] = tmp_pbbox.p.x;
287
0
        w2[3] = tmp_pbbox.p.y;
288
0
        w2[4] = tmp_pbbox.q.x;
289
0
        w2[5] = tmp_pbbox.q.y;
290
291
0
        gs_setmatrix(pgs, &save_ctm);
292
1.19M
    } else {
293
1.19M
        w2[0] = pwidth[0];
294
1.19M
        w2[1] = pwidth[1];
295
1.19M
        w2[2] = pbbox->p.x;
296
1.19M
        w2[3] = pbbox->p.y;
297
1.19M
        w2[4] = pbbox->q.x;
298
1.19M
        w2[5] = pbbox->q.y;
299
1.19M
    }
300
301
1.19M
    if (pbfont->PaintType) {
302
0
        double expand = max(1.415,
303
0
                            gs_currentmiterlimit(pgs)) *
304
0
            gs_currentlinewidth(pgs) / 2;
305
306
0
        w2[2] -= expand;
307
0
        w2[3] -= expand;
308
0
        w2[4] += expand;
309
0
        w2[5] += expand;
310
0
    }
311
312
1.19M
    if (I->ff.embolden != 0) {
313
0
        code = gs_setcharwidth((gs_show_enum *) penum, pgs, w2[0], w2[1]);
314
1.19M
    } else {
315
1.19M
        if ((code = gs_setcachedevice((gs_show_enum *) penum, pgs, w2)) < 0) {
316
0
            return (code);
317
0
        }
318
1.19M
    }
319
320
1.19M
    if ((penum->text.operation & TEXT_DO_DRAW) && (pbfont->WMode & 1)
321
0
        && pwidth[0] == 1.0) {
322
0
        *imagenow = false;
323
0
        return (gs_error_unknownerror);
324
0
    }
325
326
1.19M
    *imagenow = true;
327
1.19M
    return (code);
328
1.19M
}
329
330
static int
331
pl_fapi_set_cache_rotate(gs_text_enum_t * penum, const gs_font_base * pbfont,
332
                         const gs_string * char_name, gs_glyph cid,
333
                         const double pwidth[2], const gs_rect * pbbox,
334
                         const double Metrics2_sbw_default[4],
335
                         bool * imagenow)
336
0
{
337
0
    *imagenow = true;
338
0
    return (0);
339
0
}
340
341
342
static int
343
pl_fapi_build_char(gs_show_enum * penum, gs_gstate * pgs, gs_font * pfont,
344
                   gs_char chr, gs_glyph glyph)
345
1.19M
{
346
1.19M
    int code;
347
1.19M
    gs_matrix save_ctm;
348
1.19M
    gs_font_base *pbfont = (gs_font_base *) pfont;
349
1.19M
    pl_font_t *plfont = (pl_font_t *) pfont->client_data;
350
1.19M
    gs_fapi_server *I = pbfont->FAPI;
351
352
1.19M
    I->ff.embolden = plfont->bold_fraction;
353
1.19M
    I->ff.is_mtx_skipped = plfont->is_xl_format;
354
355
1.19M
    code =
356
1.19M
        gs_fapi_do_char(pfont, pgs, (gs_text_enum_t *) penum, NULL, false,
357
1.19M
                        NULL, NULL, chr, glyph, 0);
358
359
1.19M
    if (code == gs_error_unknownerror) {
360
0
        gs_fapi_font tmp_ff;
361
362
0
        tmp_ff.fapi_set_cache = I->ff.fapi_set_cache;
363
364
        /* save the ctm */
365
0
        gs_currentmatrix(pgs, &save_ctm);
366
367
        /* magic numbers - we don't completelely understand
368
           the translation magic used by HP.  This provides a
369
           good approximation */
370
0
        gs_translate(pgs, 1.0 / 1.15, -(1.0 - 1.0 / 1.15));
371
0
        gs_rotate(pgs, 90);
372
373
0
        I->ff.fapi_set_cache = pl_fapi_set_cache_rotate;
374
375
0
        code =
376
0
            gs_fapi_do_char(pfont, pgs, (gs_text_enum_t *) penum, NULL, false,
377
0
                            NULL, NULL, chr, glyph, 0);
378
379
0
        I->ff.fapi_set_cache = tmp_ff.fapi_set_cache;
380
381
0
        gs_setmatrix(pgs, &save_ctm);
382
0
    }
383
384
1.19M
    I->ff.embolden = 0;
385
386
1.19M
    return (code);
387
1.19M
}
388
389
/* FIXME: environment variables.... */
390
const char *
391
pl_fapi_ufst_get_fco_list(gs_memory_t * mem)
392
0
{
393
0
    return (UFSTFCOS);
394
0
}
395
396
const char *
397
pl_fapi_ufst_get_font_dir(gs_memory_t * mem)
398
0
{
399
0
    return (UFSTFONTDIR);
400
0
}
401
402
static int
403
pl_get_server_param(gs_fapi_server * I, const char *subtype,
404
                    char **server_param, int *server_param_size)
405
2.17M
{
406
2.17M
    int length = 0;
407
2.17M
    char SEPARATOR_STRING[2];
408
409
2.17M
    SEPARATOR_STRING[0] = (char)gp_file_name_list_separator;
410
2.17M
    SEPARATOR_STRING[1] = '\0';
411
412
2.17M
    length += strlen(UFSTDIRPARM);
413
2.17M
    length += strlen(UFSTFONTDIR);
414
2.17M
    length += strlen(SEPARATOR_STRING);
415
2.17M
    length += strlen(UFSTPLUGINPARM);
416
2.17M
    length += strlen(UFSTPLUGINS);
417
2.17M
    length++;
418
419
2.17M
    if ((*server_param) != NULL && (*server_param_size) >= length) {
420
1.08M
        strcpy((char *)*server_param, (char *)UFSTDIRPARM);
421
1.08M
        strcat((char *)*server_param, (char *)UFSTFONTDIR);
422
1.08M
        strcat((char *)*server_param, (char *)SEPARATOR_STRING);
423
1.08M
        strcat((char *)*server_param, (char *)UFSTPLUGINPARM);
424
1.08M
        strcat((char *)*server_param, (char *)UFSTPLUGINS);
425
1.08M
    } else {
426
1.08M
        *server_param = NULL;
427
1.08M
        *server_param_size = length;
428
1.08M
    }
429
2.17M
    return 1;
430
2.17M
}
431
432
433
static inline int
434
pl_fapi_get_mtype_font_info(gs_font * pfont, gs_fapi_font_info item,
435
                            void *data, int *size)
436
0
{
437
0
    return (gs_fapi_get_font_info(pfont, item, 0, data, size));
438
0
}
439
440
int
441
pl_fapi_get_mtype_font_name(gs_font * pfont, byte * data, int *size)
442
0
{
443
0
    return (pl_fapi_get_mtype_font_info
444
0
            (pfont, gs_fapi_font_info_name, data, size));
445
0
}
446
447
int
448
pl_fapi_get_mtype_font_number(gs_font * pfont, int *font_number)
449
0
{
450
0
    int size = (int)sizeof(*font_number);
451
452
0
    return (pl_fapi_get_mtype_font_info
453
0
            (pfont, gs_fapi_font_info_uid, font_number, &size));
454
0
}
455
456
int
457
pl_fapi_get_mtype_font_spaceBand(gs_font * pfont, uint * spaceBand)
458
0
{
459
0
    int size = (int)sizeof(*spaceBand);
460
461
0
    return (pl_fapi_get_mtype_font_info
462
0
            (pfont, gs_fapi_font_info_pitch, spaceBand, &size));
463
0
}
464
465
int
466
pl_fapi_get_mtype_font_scaleFactor(gs_font * pfont, uint * scaleFactor)
467
0
{
468
0
    int size = (int)sizeof(*scaleFactor);
469
470
0
    return (pl_fapi_get_mtype_font_info
471
0
            (pfont, gs_fapi_font_info_design_units, scaleFactor, &size));
472
0
}
473
474
static text_enum_proc_is_width_only(pl_show_text_is_width_only);
475
static text_enum_proc_release(pl_text_release);
476
477
static const gs_text_enum_procs_t null_text_procs = {
478
    NULL, NULL,
479
    pl_show_text_is_width_only, NULL,
480
    NULL, NULL,
481
    pl_text_release
482
};
483
484
static bool
485
pl_show_text_is_width_only(const gs_text_enum_t *pte)
486
1.51M
{
487
1.51M
    return(true);
488
1.51M
}
489
490
void pl_text_release(gs_text_enum_t *pte, client_name_t cname)
491
1.51M
{
492
1.51M
   gx_cpath_free((gx_clip_path *)pte->pcpath, "gx_default_text_release");
493
1.51M
   pte->pcpath = NULL;
494
1.51M
   rc_decrement_only(pte->dev, cname);
495
1.51M
   rc_decrement_only(pte->imaging_dev, cname);
496
1.51M
  return;
497
1.51M
}
498
499
static int
500
pl_fapi_set_cache_metrics(gs_text_enum_t * penum, const gs_font_base * pbfont,
501
                         const gs_string * char_name, gs_glyph cid,
502
                         const double pwidth[2], const gs_rect * pbbox,
503
                         const double Metrics2_sbw_default[4],
504
                         bool * imagenow)
505
1.51M
{
506
1.51M
    penum->returned.total_width.x = pwidth[0];
507
1.51M
    penum->returned.total_width.y = pwidth[1];
508
509
1.51M
    *imagenow = false;
510
1.51M
    return (gs_error_unknownerror);
511
1.51M
}
512
513
static int
514
pl_fapi_char_metrics(const pl_font_t * plfont, const void *vpgs,
515
                     gs_char char_code, float metrics[4])
516
1.62M
{
517
1.62M
    int code = 0;
518
1.62M
    gs_text_enum_t *penum1;
519
1.62M
    gs_font *pfont = plfont->pfont;
520
1.62M
    gs_font_base *pbfont = (gs_font_base *) pfont;
521
1.62M
    gs_text_params_t text;
522
1.62M
    gs_char buf[2];
523
1.62M
    gs_gstate *rpgs = (gs_gstate *) vpgs;
524
    /* NAFF: undefined glyph would be better handled inside FAPI */
525
1.62M
    gs_char chr = char_code;
526
1.62M
    gs_glyph unused_glyph = GS_NO_GLYPH;
527
1.62M
    gs_glyph glyph;
528
1.62M
    gs_matrix mat = {72.0, 0.0, 0.0, 72.0, 0.0, 0.0};
529
1.62M
    gs_matrix fmat;
530
1.62M
    gs_fapi_font tmp_ff;
531
532
1.62M
    if (pfont->FontType == ft_MicroType) {
533
0
        glyph = char_code;
534
1.62M
    } else {
535
1.62M
        glyph = pl_tt_encode_char(pfont, chr, unused_glyph);
536
1.62M
    }
537
538
1.62M
    if (pfont->WMode & 1) {
539
0
        gs_glyph vertical = pl_font_vertical_glyph(glyph, plfont);
540
541
0
        if (vertical != GS_NO_GLYPH)
542
0
            glyph = vertical;
543
0
    }
544
545
    /* undefined character */
546
1.62M
    if (glyph == 0xffff || glyph == GS_NO_GLYPH) {
547
104k
        metrics[0] = metrics[1] = metrics[2] = metrics[3] = 0;
548
104k
        code = 1;
549
1.51M
    } else {
550
1.51M
        gs_fapi_server *I = pbfont->FAPI;
551
1.51M
        gs_gstate lpgs;
552
1.51M
        gs_gstate *pgs = &lpgs;
553
554
        /* This is kind of naff, but it's *much* cheaper to copy
555
         * the parts of the gstate we need, than gsave/grestore
556
         */
557
1.51M
        memset(pgs, 0x00, sizeof(lpgs));
558
1.51M
        pgs->memory = rpgs->memory;
559
1.51M
        pgs->ctm = rpgs->ctm;
560
1.51M
        pgs->in_cachedevice = CACHE_DEVICE_NOT_CACHING;
561
1.51M
        pgs->device = rpgs->device;
562
1.51M
        pgs->log_op = rpgs->log_op;
563
1.51M
        *(pgs->color) = *(rpgs->color);
564
565
1.51M
        tmp_ff.fapi_set_cache = I->ff.fapi_set_cache;
566
1.51M
        I->ff.fapi_set_cache = pl_fapi_set_cache_metrics;
567
568
1.51M
        gs_setmatrix(pgs, &mat);
569
1.51M
        fmat = pfont->FontMatrix;
570
1.51M
        pfont->FontMatrix = pfont->orig_FontMatrix;
571
1.51M
        (void)gs_setfont(pgs, pfont);
572
573
1.51M
        I->ff.is_mtx_skipped = plfont->is_xl_format;
574
575
1.51M
        buf[0] = char_code;
576
1.51M
        buf[1] = '\0';
577
578
1.51M
        text.operation = TEXT_FROM_CHARS | TEXT_DO_NONE | TEXT_RETURN_WIDTH;
579
1.51M
        text.data.chars = buf;
580
1.51M
        text.size = 1;
581
582
1.51M
        if ((penum1 = gs_text_enum_alloc(pfont->memory, pgs,
583
1.51M
                      "pl_fapi_char_metrics")) != NULL) {
584
585
1.51M
            if ((code = gs_text_enum_init(penum1, &null_text_procs,
586
1.51M
                                 NULL, pgs, &text, pfont,
587
1.51M
                                 NULL, pfont->memory)) >= 0) {
588
589
1.51M
                code = gs_fapi_do_char(pfont, pgs, penum1, plfont->font_file, false,
590
1.51M
                            NULL, NULL, char_code, glyph, 0);
591
592
1.51M
                if (code >= 0 || code == gs_error_unknownerror) {
593
1.51M
                    metrics[0] = metrics[1] = 0;
594
1.51M
                    metrics[2] = penum1->returned.total_width.x;
595
1.51M
                    metrics[3] = penum1->returned.total_width.y;
596
1.51M
                    if (code < 0)
597
1.51M
                        code = 0;
598
1.51M
                }
599
1.51M
            }
600
1.51M
            rc_decrement(penum1, "pl_fapi_char_metrics");
601
1.51M
        }
602
1.51M
        pfont->FontMatrix = fmat;
603
1.51M
        I->ff.fapi_set_cache = tmp_ff.fapi_set_cache;
604
1.51M
    }
605
1.62M
    return (code);
606
1.62M
}
607
608
static int
609
pl_fapi_char_width(const pl_font_t * plfont, const void *pgs,
610
                   gs_char char_code, gs_point * pwidth)
611
1.33M
{
612
1.33M
    float metrics[4];
613
1.33M
    int code = 0;
614
615
1.33M
    code = pl_fapi_char_metrics(plfont, pgs, char_code, metrics);
616
617
1.33M
    pwidth->x = metrics[2];
618
1.33M
    pwidth->y = 0;
619
620
1.33M
    return (code);
621
1.33M
}
622
623
static gs_glyph
624
pl_fapi_encode_char(gs_font * pfont, gs_char pchr, gs_glyph_space_t not_used)
625
0
{
626
0
    return (gs_glyph) pchr;
627
0
}
628
629
int
630
pl_fapi_passfont(pl_font_t * plfont, int subfont, char *fapi_request,
631
                 char *file_name, byte * font_data, int font_data_len)
632
1.08M
{
633
1.08M
    char *fapi_id = NULL;
634
1.08M
    int code = 0;
635
1.08M
    gs_string fdata;
636
1.08M
    gs_font *pfont = plfont->pfont;
637
1.08M
    gs_fapi_font local_pl_ff_stub;
638
639
1.08M
    if (!gs_fapi_available(pfont->memory, NULL)) {
640
0
        return (code);
641
0
    }
642
643
1.08M
    local_pl_ff_stub = pl_ff_stub;
644
1.08M
    local_pl_ff_stub.is_mtx_skipped = plfont->is_xl_format;
645
646
1.08M
    fdata.data = font_data;
647
1.08M
    fdata.size = font_data_len;
648
649
    /* The plfont should contain everything we need, but setting the client data for the server
650
     * to pbfont makes as much sense as setting it to NULL.
651
     */
652
1.08M
    gs_fapi_set_servers_client_data(pfont->memory,
653
1.08M
                                    (const gs_fapi_font *)&local_pl_ff_stub,
654
1.08M
                                    pfont);
655
656
1.08M
    code =
657
1.08M
        gs_fapi_passfont(pfont, subfont, (char *)file_name, &fdata,
658
1.08M
                         (char *)fapi_request, NULL, (char **)&fapi_id,
659
1.08M
                         NULL, pl_get_server_param);
660
661
1.08M
    if (code < 0 || fapi_id == NULL) {
662
4
        return code;
663
4
    }
664
665
1.08M
    pfont->procs.build_char = pl_fapi_build_char;
666
1.08M
    if (pfont->FontType == ft_MicroType) {
667
0
        pfont->procs.encode_char = pl_fapi_encode_char;
668
0
    }
669
1.08M
    plfont->char_width = pl_fapi_char_width;
670
1.08M
    plfont->char_metrics = pl_fapi_char_metrics;
671
672
1.08M
    return (code);
673
1.08M
}
674
675
bool
676
pl_fapi_ufst_available(gs_memory_t * mem)
677
10.6k
{
678
10.6k
    gs_fapi_server *serv = NULL;
679
10.6k
    int code = gs_fapi_find_server(mem, (char *)"UFST", &serv, pl_get_server_param);
680
681
10.6k
    if (code == 0 && serv != NULL) {
682
0
        return (true);
683
10.6k
    } else {
684
10.6k
        return (false);
685
10.6k
    }
686
10.6k
}