Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/* Copyright (C) 1995, 1996, 1997, 1998, 1999, 2001 Aladdin Enterprises.  All rights reserved.
2
 
3
  This software is provided AS-IS with no warranty, either express or
4
  implied.
5
 
6
  This software is distributed under license and may not be copied,
7
  modified or distributed except as expressly authorized under the terms
8
  of the license contained in the file LICENSE in this distribution.
9
 
10
  For more information about licensing, please refer to
11
  http://www.ghostscript.com/licensing/. For information on
12
  commercial licensing, go to http://www.artifex.com/licensing/ or
13
  contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14
  San Rafael, CA  94903, U.S.A., +1(415)492-9861.
15
*/
16
 
17
/* $Id: fapiufst.c,v 1.24 2004/02/18 14:41:50 igor Exp $ */
18
/* Agfa UFST plugin */
19
 
20
/* GS includes : */
21
#include "stdio_.h"
22
#include "memory_.h"
23
#include "math_.h"
24
#include "ierrors.h"
25
#include "iplugin.h"
26
#include "ifapi.h"
27
/* UFST includes : */
28
#include "cgconfig.h"
29
#include "port.h"
30
#include "shareinc.h"
31
#include "t1isfnt.h"
32
#include "cgmacros.h"
33
#include "sfntenum.h"
34
#define DOES_ANYONE_USE_THIS_STRUCTURE /* see TTPCLEO.H, UFST 4.2 */
35
#include "ttpcleo.h"
36
#undef  DOES_ANYONE_USE_THIS_STRUCTURE
37
/* GS includes : */
38
#include "gxfapi.h"
39
 
40
GLOBAL const SW16 trace_sw = 0; /* UFST 4.3 wants it. */
41
 
42
GLOBAL UW16  PCLswapHdr( FSP LPUB8 p, UW16 gifct ); /* UFST header doesn't define it. */
43
 
44
typedef struct pcleo_glyph_list_elem_s pcleo_glyph_list_elem;
45
struct pcleo_glyph_list_elem_s {
46
    UW16 chId;
47
    pcleo_glyph_list_elem *next;
48
    /* more data follows here depending on font type */
49
};
50
 
51
typedef struct fco_list_elem_s fco_list_elem;
52
struct fco_list_elem_s {
53
    int open_count;
54
    SW16 fcHandle;
55
    char *file_path;
56
    fco_list_elem *next;
57
};
58
 
59
typedef struct {
60
    SL32 font_id;
61
    uint tt_font_body_offset;
62
    UW16 is_disk_font;
63
    UW16 font_type;
64
    UW16 platformId;
65
    UW16 specificId;
66
    pcleo_glyph_list_elem *glyphs;
67
    char decodingID[12];
68
} ufst_common_font_data;
69
 
70
typedef struct { 
71
    PCLETTO_CHR_HDR h;
72
    UW16   add_data;
73
    UW16   charDataSize;
74
    UW16   glyphID;
75
} PCLETTO_CHDR;
76
 
77
typedef struct fapi_ufst_server_s fapi_ufst_server;
78
struct fapi_ufst_server_s {
79
    FAPI_server If;
80
    int bInitialized;
81
    FAPI_font *ff;
82
    i_plugin_client_memory client_mem;
83
    IF_STATE IFS;
84
    FONTCONTEXT fc;
85
    void *char_data;
86
    bool bRaster;
87
    double tran_xx, tran_xy, tran_yx, tran_yy;
88
    fco_list_elem *fco_list;
89
    FAPI_retcode callback_error;
90
    FAPI_metrics_type metrics_type;
91
    FracInt sb_x, aw_x; /* replaced PS metrics. */
92
};
93
 
94
/* Type casts : */
95
 
96
private inline fapi_ufst_server *If_to_I(FAPI_server *If)
97
{   return (fapi_ufst_server *)If;
98
}
99
 
100
private inline fapi_ufst_server *IFS_to_I(IF_STATE *pIFS)
101
{   return (fapi_ufst_server *)((char *)pIFS - offset_of(fapi_ufst_server, IFS));
102
}
103
 
104
/*------------------ FAPI_server members ------------------------------------*/
105
 
106
private inline void release_char_data_inline(fapi_ufst_server *r)
107
{   /*  The server keeps character raster between calls to get_char_raster_metrics
108
        and get_char_raster, as well as between calls to get_char_outline_metrics
109
        and get_char_outline. Meanwhile this regular
110
        sequence of calls may be interrupted by an error in CDefProc or setchachedevice2,
111
        which may be invoked between them. In this case Ghostscript
112
        is unable to provide a signal to FAPI that the data are not
113
        longer needed. This would cause memory leaks in UFST heap.
114
        To work around this, appropriate server's entries check whether
115
        raster data were left after a previous call, and ultimately release them.
116
        This function provides it.
117
    */
118
    if (r->char_data != NULL) {
119
        CHARfree(&r->IFS, (MEM_HANDLE)r->char_data);
120
        r->char_data = 0;
121
    }
122
}
123
 
124
private FAPI_retcode open_UFST(fapi_ufst_server *r)
125
{   IFCONFIG   config_block;
126
    int code;
127
 
128
    if ((code = CGIFinit(&r->IFS)) != 0)
129
	return code;
130
    r->IFS.mem_avail[BUFFER_POOL]  = 6000000L; /* For Asian TT fonts with vertical writing mode. */
131
    config_block.num_files = 10;
132
    config_block.bit_map_width = 1;
133
    if ((code = CGIFconfig(&r->IFS, &config_block)) != 0)
134
	return code;
135
    if ((code = CGIFenter(&r->IFS)) != 0)
136
	return code;
137
    return 0;
138
}		      
139
 
140
private FAPI_retcode ensure_open(FAPI_server *server)
141
{   fapi_ufst_server *r = If_to_I(server);
142
 
143
    if (r->bInitialized)
144
        return 0;
145
    r->bInitialized = 1;
146
    return open_UFST(r);
147
}
148
 
149
private UW16 get_font_type(FILE *f)
150
{   char buf[20], mark_PS[]="%!";
151
    int i;
152
 
153
    if (fread(buf, 1, sizeof(buf), f) != sizeof(buf))
154
        return 0;
155
    if (buf[0] == 0x13 || buf[0] == 0x14) /* fixme : don't know how to do correctly. */
156
        return FC_FCO_TYPE;
157
    for (i = 0; i < sizeof(buf) - sizeof(mark_PS); i++)
158
        if(!memcmp(buf + i, mark_PS, sizeof(mark_PS) - 1))
159
            return FC_PST1_TYPE;
160
    if (buf[0] == '\0' && buf[1] == '\1')
161
        return FC_TT_TYPE;
162
    if (buf[0] == 't' && buf[1] == 't')
163
        return FC_TT_TYPE;
164
    return 0; /* fixme : unknown type - actually an error. */
165
}
166
 
167
 
168
private int choose_decoding_PS(fapi_ufst_server *r, ufst_common_font_data *d, const char *cmapId)
169
{ strncpy(d->decodingID, "Latin1", sizeof(d->decodingID));
170
  /*    fixme : must depend on charset used in the font.
171
        Particulartly Symbol fonts need a different decoding.
172
  */
173
  return 1;
174
}
175
 
176
private int choose_decoding_TT(fapi_ufst_server *r, ufst_common_font_data *d, const char *cmapId)
177
{   int platId, specId, i;
178
    CMAP_QUERY q;
179
    UW16 font_access;
180
    bool failed;
181
    void *p = (d->is_disk_font ? (void *)(d + 1) : (void *)((UB8 *)d + d->tt_font_body_offset));
182
 
183
    if (sscanf(cmapId, "%d.%d", &platId, &specId) != 2)
184
        return 0;
185
    font_access = r->IFS.font_access;
186
    r->IFS.font_access = (d->is_disk_font ? DISK_ACCESS : ROM_ACCESS);
187
    failed = CGIFtt_cmap_query(&r->IFS, p, r->fc.ttc_index, &q);
188
    r->IFS.font_access = font_access;
189
    if(failed)
190
        return 0;
191
    for (i = 0; i < q.numCmap; i++)
192
        if (q.entry[i].platId == platId && q.entry[i].specId == specId) {
193
            d->platformId = platId;
194
            d->specificId = specId;
195
            return 1;
196
        }
197
    return 0;
198
}
199
 
200
private void scan_xlatmap(fapi_ufst_server *r, ufst_common_font_data *d, const char *xlatmap, const char *font_kind, 
201
                                    int (*choose_proc)(fapi_ufst_server *r, ufst_common_font_data *d, const char *cmapId))
202
{   const char *p = xlatmap;
203
 
204
    while(*p) {
205
        int good_kind =!strcmp(p, font_kind);
206
        p += strlen(p) + 2;
207
        while(*p) {
208
            const char *cmapId = p, *decodingID = p + strlen(p) + 1;
209
            strncpy(d->decodingID, decodingID, sizeof(d->decodingID));
210
            if (!decodingID[0])
211
                break;
212
            p = decodingID + strlen(decodingID) + 1;
213
            if (good_kind)
214
                if (choose_proc(r, d, cmapId))
215
                    return;
216
        }
217
    }
218
    d->decodingID[0] = 0;
219
}
220
 
221
private void choose_decoding(fapi_ufst_server *r, ufst_common_font_data *d, const char *xlatmap)
222
{   if (xlatmap != 0)
223
        switch (d->font_type) {
224
            case FC_IF_TYPE: /* fixme */ break;
225
            case FC_PST1_TYPE: scan_xlatmap(r, d, xlatmap, "PostScript", choose_decoding_PS); break;
226
            case FC_TT_TYPE:   scan_xlatmap(r, d, xlatmap, "TrueType", choose_decoding_TT); break;
227
            case FC_FCO_TYPE:  scan_xlatmap(r, d, xlatmap, "PostScript", choose_decoding_PS/* fixme */); break;
228
        } 
229
}
230
 
231
private inline void store_word(byte **p, ushort w)
232
{   *((*p)++) = w / 256;
233
    *((*p)++) = w % 256;
234
 
235
}
236
 
237
private LPUB8 get_TT_glyph(fapi_ufst_server *r, FAPI_font *ff, UW16 chId)
238
{   pcleo_glyph_list_elem *g;
239
    PCLETTO_CHDR *h;
240
    ufst_common_font_data *d = (ufst_common_font_data *)r->fc.font_hdr - 1;
241
    LPUB8 q;
242
    ushort glyph_length = ff->get_glyph(ff, chId, 0, 0);
243
    bool use_XL_format = ff->is_mtx_skipped;
244
 
245
    /*
246
     * The client must set ff->is_mtx_skipped iff
247
     * it requests replaced lsb for True Type.
248
     * If it is set, replaced width to be supplied.
249
     * This constraing is derived from UFST restriction :
250
     * the font header format must be compatible with
251
     * glyph header format.
252
     */
253
 
254
    if (glyph_length == (ushort)-1) {
255
        r->callback_error = e_invalidfont;
256
        return 0;
257
    }
258
    g = (pcleo_glyph_list_elem *)r->client_mem.alloc(&r->client_mem, 
259
	    sizeof(pcleo_glyph_list_elem) + 
260
	    (use_XL_format ? 12 : sizeof(PCLETTO_CHDR)) + glyph_length + 2, 
261
	    "PCLETTO char");
262
    if (g == 0) {
263
        r->callback_error = e_VMerror;
264
        return 0;
265
    }
266
    g->chId = chId;
267
    g->next = d->glyphs;
268
    d->glyphs = g;
269
    h = (PCLETTO_CHDR *)(g + 1);
270
    h->h.format = 15;
271
    if (use_XL_format) {
272
	h->h.continuation = 2; 
273
	q = (LPUB8)h + 2;
274
	store_word(&q, (ushort)(glyph_length + 10));
275
	store_word(&q, (ushort)(r->sb_x >> r->If.frac_shift)); /* see can_replace_metrics */
276
	store_word(&q, (ushort)(r->aw_x >> r->If.frac_shift));
277
	store_word(&q, 0);
278
	store_word(&q, chId);
279
    } else {
280
	h->h.continuation = 0;
281
	h->h.descriptorsize = 4;
282
	h->h.class = 15;
283
	h->add_data = 0;
284
	q = (LPUB8)&h->charDataSize;
285
	store_word(&q, (ushort)(glyph_length + 4));
286
	store_word(&q, chId);
287
    }
288
    if (ff->get_glyph(ff, chId, (LPUB8)q, glyph_length) == (ushort)-1) {
289
        r->callback_error = e_invalidfont;
290
        return 0;
291
    }
292
    q += glyph_length;
293
    store_word(&q, 0); /* checksum */
294
    return (LPUB8)h;
295
    /*
296
     * The metrics replacement here is done only for the case
297
     * corresponding to non-disk TT fonts with MetricsCount != 0;
298
     * Other cases are not supported because UFST cannot handle them.
299
     * Here we don't take care of cases which can_replace_metrics rejects.
300
     *
301
     * We don't care of metrics for subglyphs, because
302
     * it is ignored by TT interpreter.
303
     */
304
}
305
 
306
private LPUB8 get_T1_glyph(fapi_ufst_server *r, FAPI_font *ff, UW16 chId)
307
{   ushort glyph_length = ff->get_glyph(ff, chId, 0, 0);
308
    LPUB8 q;
309
    pcleo_glyph_list_elem *g = (pcleo_glyph_list_elem *)r->client_mem.alloc(&r->client_mem, sizeof(pcleo_glyph_list_elem) + sizeof(PS_CHAR_HDR) + 2 + 2 + glyph_length + 1, "PSEO char");
310
    PS_CHAR_HDR *h;
311
    ufst_common_font_data *d = (ufst_common_font_data *)r->fc.font_hdr - 1;
312
 
313
    if (g == 0 || glyph_length == (ushort)-1) {
314
        r->callback_error = e_invalidfont;
315
        return 0;
316
    }
317
    g->chId = chId;
318
    g->next = d->glyphs;
319
    d->glyphs = g;
320
    h = (PS_CHAR_HDR *)(g + 1);
321
    h->format = 30;           /* raster=4, DJ=5, IF=10, TT=15, PS=30 */
322
    h->continuation = 0;     /* always 0 */
323
    h->descriptorsize = 2;   /* always 2 */
324
    h->class = 11;           /* contour=3, compound=4, tt=10, ps=11 */
325
    h->len = 0;              /* # of bytes to follow (not including csum) */
326
    q = (byte *)h + sizeof(*h);
327
    q[0] = 0; /* Namelen */
328
    q[1] = 0; /* Namelen */
329
    q[2] = (glyph_length) / 256; /* Datalen */
330
    q[3] = (glyph_length) % 256; /* Datalen */
331
    /* Glyph name goes here, but we don't use it. */
332
    q+=4;
333
    glyph_length = ff->get_glyph(ff, chId, q, glyph_length);
334
    q += glyph_length;
335
    *q = 1; /* Decrypt flag */
336
    return (LPUB8)h;
337
}
338
 
339
private pcleo_glyph_list_elem * find_glyph(ufst_common_font_data *d, UW16 chId)
340
{   pcleo_glyph_list_elem *e;
341
 
342
    for (e = d->glyphs; e != 0; e = e->next)
343
        if (e->chId == chId)
344
            return e;
345
    return 0;
346
}
347
 
348
private LPUB8 gs_PCLEO_charptr(LPUB8 pfont_hdr, UW16  sym_code)
349
{   /* never called */
350
    /*  We would like to do this :
351
        r->callback_error = e_unregistered;
352
        (see gs_PCLglyphID2Ptr)
353
        but we can't due to the reentrancy problem of UFST.
354
    */
355
    return 0;
356
}
357
 
358
private LPUB8 gs_PCLchId2ptr(IF_STATE *pIFS, UW16 chId)
359
{   fapi_ufst_server *r = IFS_to_I(pIFS);
360
    FAPI_font *ff = r->ff;
361
    ufst_common_font_data *d = (ufst_common_font_data *)r->fc.font_hdr - 1;
362
    pcleo_glyph_list_elem *g = find_glyph(d, chId);
363
    LPUB8 result = 0;
364
 
365
    if (g != 0)
366
        result = (LPUB8)(g + 1);
367
    if ((r->fc.format & FC_FONTTYPE_MASK) == FC_PST1_TYPE)
368
        result = get_T1_glyph(r, ff, chId);
369
    if ((r->fc.format & FC_FONTTYPE_MASK) == FC_TT_TYPE)
370
        result = get_TT_glyph(r, ff, chId);
371
    return result;
372
}
373
 
374
private LPUB8 gs_PCLglyphID2Ptr(IF_STATE *pIFS, UW16 glyphID)
375
{   return gs_PCLchId2ptr(pIFS, glyphID);
376
}
377
 
378
private inline void pack_word(LPUB8 *p, UW16 v)
379
{   LPUB8 q = (LPUB8)&v;
380
 
381
#if (BYTEORDER == LOHI) /* defied in UFST includes */
382
         (*p)[1] = q[0];
383
         (*p)[0] = q[1];
384
#else
385
        *(UW16 *)(*p) = v;
386
#endif
387
    *p += 2;
388
}
389
 
390
private inline void pack_long(LPUB8 *p, UL32 v)
391
{   LPUB8 q = (LPUB8)&v;
392
 
393
#if (BYTEORDER == LOHI) /* defied in UFST includes */
394
         (*p)[3] = q[0];
395
         (*p)[2] = q[1];
396
         (*p)[1] = q[2];
397
         (*p)[0] = q[3];
398
#else
399
        *(UL32 *)(*p) = v;
400
#endif
401
    *p += 4;
402
}
403
 
404
private inline void pack_float(LPUB8 *p, float v)
405
{   sprintf((char *)(*p), "%f", v);
406
    *p += strlen((const char *)*p) + 1;
407
}
408
 
409
#define PACK_ZERO(p) *(p++) = 0
410
#define PACK_BYTE(p, c) *(p++) = c
411
#define PACK_WORD(p, i, var) pack_word(&p, ff->get_word(ff, var, i))
412
#define PACK_LONG(p, i, var) pack_long(&p, ff->get_long(ff, var, i))
413
 
414
private void pack_pseo_word_array(fapi_ufst_server *r, FAPI_font *ff, UB8 **p, UW16 max_count, fapi_font_feature count_id, fapi_font_feature array_id)
415
{   UW16 k = min(ff->get_word(ff, count_id, 0), max_count), j;
416
 
417
    pack_word(p, k);
418
    for (j = 0; j < k; j++)
419
        PACK_WORD(*p, j, array_id);
420
    for (; j < max_count; j++)
421
        pack_word(p, 0);
422
}
423
 
424
private void pack_pseo_fhdr(fapi_ufst_server *r, FAPI_font *ff, UB8 *p)
425
{   ushort j, n, skip = 0;
426
 
427
    while ((UL32)p & 0x03) /* align to QUADWORD */
428
	PACK_ZERO(p);
429
    pack_long(&p, 1);  /* format = 1 */
430
    for (j = 0; j < 6; j++)
431
        pack_float(&p, ff->get_float(ff, FAPI_FONT_FEATURE_FontMatrix, j));
432
    while ((UL32)p & 0x03) /* align to QUADWORD */
433
	PACK_ZERO(p);
434
    /* UFST has no definition for PSEO structure, so implement serialization : */
435
    PACK_LONG(p, 0, FAPI_FONT_FEATURE_UniqueID);
436
    PACK_LONG(p, 0, FAPI_FONT_FEATURE_BlueScale);
437
    PACK_WORD(p, 0, FAPI_FONT_FEATURE_Weight);
438
    PACK_WORD(p, 0, FAPI_FONT_FEATURE_ItalicAngle);
439
    PACK_WORD(p, 0, FAPI_FONT_FEATURE_IsFixedPitch);
440
    PACK_WORD(p, 0, FAPI_FONT_FEATURE_UnderLinePosition);
441
    PACK_WORD(p, 0, FAPI_FONT_FEATURE_UnderlineThickness);
442
    PACK_WORD(p, 0, FAPI_FONT_FEATURE_FontType);
443
    PACK_WORD(p, 0, FAPI_FONT_FEATURE_FontBBox);
444
    PACK_WORD(p, 1, FAPI_FONT_FEATURE_FontBBox);
445
    PACK_WORD(p, 2, FAPI_FONT_FEATURE_FontBBox);
446
    PACK_WORD(p, 3, FAPI_FONT_FEATURE_FontBBox);
447
    pack_pseo_word_array(r, ff, &p, 14, FAPI_FONT_FEATURE_BlueValues_count, FAPI_FONT_FEATURE_BlueValues);
448
    pack_pseo_word_array(r, ff, &p, 10, FAPI_FONT_FEATURE_OtherBlues_count, FAPI_FONT_FEATURE_OtherBlues);
449
    pack_pseo_word_array(r, ff, &p, 14, FAPI_FONT_FEATURE_FamilyBlues_count, FAPI_FONT_FEATURE_FamilyBlues);
450
    pack_pseo_word_array(r, ff, &p, 10, FAPI_FONT_FEATURE_FamilyOtherBlues_count, FAPI_FONT_FEATURE_FamilyOtherBlues);
451
    PACK_WORD(p, 0, FAPI_FONT_FEATURE_BlueShift);
452
    PACK_WORD(p, 0, FAPI_FONT_FEATURE_BlueFuzz);
453
    PACK_WORD(p, 0, FAPI_FONT_FEATURE_StdHW);
454
    PACK_WORD(p, 0, FAPI_FONT_FEATURE_StdVW);
455
    pack_pseo_word_array(r, ff, &p, 12, FAPI_FONT_FEATURE_StemSnapH_count, FAPI_FONT_FEATURE_StemSnapH);
456
    pack_pseo_word_array(r, ff, &p, 12, FAPI_FONT_FEATURE_StemSnapV_count, FAPI_FONT_FEATURE_StemSnapV);
457
    PACK_WORD(p, 0, FAPI_FONT_FEATURE_ForceBold);
458
    PACK_WORD(p, 0, FAPI_FONT_FEATURE_LanguageGroup);
459
    PACK_WORD(p, 0, FAPI_FONT_FEATURE_lenIV);
460
    for (j = 0; j < 12; j++)
461
        PACK_ZERO(p), PACK_ZERO(p);     /* Reserved2 */
462
    /* max data size = 107 words + 6 floats in ASCII */
463
    n = ff->get_word(ff, FAPI_FONT_FEATURE_Subrs_count, 0);
464
    pack_word(&p, n);
465
    for (j = 0; j < n; j++) {
466
        ushort subr_len = ff->get_subr(ff, j, 0, 0);
467
        if (subr_len != 0) {
468
            pack_word(&p, j);
469
            pack_word(&p, subr_len);
470
            PACK_BYTE(p, 1); /* is_decrypted */
471
            ff->get_subr(ff, j, p, subr_len);
472
            p += subr_len;
473
        } else
474
            skip = 1;
475
    }
476
    if (skip)
477
        pack_word(&p, 0xFFFF);
478
}
479
 
480
private void enumerate_fco(fapi_ufst_server *r, const char *font_file_path)
481
{   /* development perpose only */
482
#if 0
483
        UW16 i;
484
        for (i = 0; ; i++) {
485
            UW16 size;
486
            TTFONTINFOTYPE *pBuffer;
487
            UW16 code = CGIFfco_Access(&r->IFS, (LPUB8)font_file_path, i, TFATRIB_KEY, &size, NULL);
488
            if (code)
489
                break;
490
            pBuffer = (TTFONTINFOTYPE *)malloc(size);
491
            if (pBuffer == 0)
492
                break;
493
            code = CGIFfco_Access(&r->IFS, (LPUB8)font_file_path, i, TFATRIB_KEY, &size, (SB8 *)pBuffer);
494
            if (code)
495
                break;
496
            {   char *tfName          = (char *)pBuffer + pBuffer->tfName;
497
                char *pcltTypeface    = (char *)pBuffer + pBuffer->pcltTypeface;
498
                char *pcltFileName    = (char *)pBuffer + pBuffer->pcltFileName;
499
                char *familyName      = (char *)pBuffer + pBuffer->familyName;
500
                char *weightName      = (char *)pBuffer + pBuffer->weightName;
501
                char *copyrightNotice = (char *)pBuffer + pBuffer->copyrightNotice;
502
                pBuffer += 0; /* a place for breakpoint */
503
            }
504
            free(pBuffer);
505
            (void)code;
506
        }
507
#endif
508
}
509
 
510
private char *my_strdup(fapi_ufst_server *r, const char *s, const char *cname)
511
{   int l = strlen(s) + 1;
512
    char *p = (char *)r->client_mem.alloc(&r->client_mem, l, cname);
513
 
514
    if (p != 0)
515
        memcpy(p, s, l);
516
    return p;
517
}
518
 
519
private FAPI_retcode fco_open(fapi_ufst_server *r, const char *font_file_path, fco_list_elem **result)
520
{   fco_list_elem *e = r->fco_list;
521
    int code;
522
 
523
    for (; e != 0; e = e->next) {
524
        if (!strcmp(e->file_path, font_file_path))
525
            break;
526
    }
527
    if (e == 0) {
528
        SW16 fcHandle;
529
        if ((code = CGIFfco_Open(&r->IFS, (UB8 *)font_file_path, &fcHandle)) != 0)
530
	    return code;
531
        e = (fco_list_elem *)r->client_mem.alloc(&r->client_mem, sizeof(*e), "fco_list_elem");
532
        if (e == 0) {
533
            CGIFfco_Close(&r->IFS, fcHandle);
534
            return e_VMerror;
535
        }
536
        e->open_count = 0;
537
        e->fcHandle = fcHandle;
538
        e->file_path = my_strdup(r, font_file_path, "fco_file_path");
539
        if (e->file_path == 0) {
540
            CGIFfco_Close(&r->IFS, fcHandle);
541
            r->client_mem.free(&r->client_mem, e, "fco_list_elem");
542
            return e_VMerror;
543
        }
544
        e->next = r->fco_list;
545
        r->fco_list = e;
546
    }
547
    e->open_count++;
548
    *result = e;
549
    return 0;
550
}
551
 
552
private FAPI_retcode make_font_data(fapi_ufst_server *r, const char *font_file_path, int subfont, FAPI_font *ff, ufst_common_font_data **return_data)
553
{   ulong area_length = sizeof(ufst_common_font_data), tt_size = 0;
554
    LPUB8 buf;
555
    PCLETTO_FHDR *h;
556
    ufst_common_font_data *d;
557
    bool use_XL_format = ff->is_mtx_skipped;
558
    int code;
559
 
560
    *return_data = 0;
561
    r->fc.ttc_index = subfont;
562
    if (ff->font_file_path == NULL) {
563
        area_length += PCLETTOFONTHDRSIZE;
564
        if (ff->is_type1) {
565
            int subrs_count  = ff->get_word(ff, FAPI_FONT_FEATURE_Subrs_count, 0);
566
            int subrs_length = ff->get_long(ff, FAPI_FONT_FEATURE_Subrs_total_size, 0);
567
            int subrs_area_size = subrs_count * 5 + subrs_length + 2;
568
            area_length += 360 + subrs_area_size; /* some inprecise - see pack_pseo_fhdr */
569
        } else {
570
            tt_size  = ff->get_long(ff, FAPI_FONT_FEATURE_TT_size, 0);
571
            if (tt_size == 0)
572
                return e_invalidfont;
573
            area_length += tt_size + (use_XL_format ? 6 : 4) + 4 + 2;
574
        }
575
    } else
576
        area_length += strlen(font_file_path) + 1;
577
    buf = r->client_mem.alloc(&r->client_mem, area_length, "ufst font data");
578
    if (buf == 0)
579
        return e_VMerror;
580
    d = (ufst_common_font_data *)buf;
581
    d->tt_font_body_offset = 0;
582
    d->platformId = 0;
583
    d->specificId = 0;
584
    d->decodingID[0] = 0;
585
    d->glyphs = 0;
586
    d->font_id = 0;
587
    d->is_disk_font = (ff->font_file_path != NULL);
588
    if (d->is_disk_font) {
589
        FILE *f = fopen(font_file_path, "rb"); /* note: gp_fopen isn't better since UFST calls fopen. */
590
        if (f == NULL)
591
            return e_undefinedfilename;
592
        memcpy(d + 1, font_file_path, strlen(font_file_path) + 1);
593
        d->font_type = get_font_type(f);
594
        fclose(f);
595
        if (d->font_type == FC_FCO_TYPE) {
596
            fco_list_elem *e;
597
            if ((code = fco_open(r, font_file_path, &e)) != 0)
598
		return code;
599
            enumerate_fco(r, font_file_path); /* development perpose only */
600
            d->font_id = (e->fcHandle << 16) | subfont;
601
        }
602
    } else {
603
        d->font_type = (ff->is_type1 ? FC_PST1_TYPE : FC_TT_TYPE);
604
        h = (PCLETTO_FHDR *)(buf + sizeof(ufst_common_font_data));
605
        h->fontDescriptorSize = PCLETTOFONTHDRSIZE;
606
        h->descriptorFormat = 15;
607
        h->fontType = 11; /* wrong */                /*  3- 11=Unicode; 0,1,2 also possible */
608
        h->style_msb = 0; /* wrong */               /*  4- from PCLT table in TrueType font */
609
        h->reserved1 = 0;
610
        h->baselinePosition = 0; /* wrong */        /*  6- from head table in TT font; = 0 */
611
        h->cellWidth = 1024; /* wrong */               /*  8- head, use xMax - xMin */
612
        h->cellHeight = 1024; /* wrong */             /* 10- head, use yMax - yMin */
613
        h->orientation = 0;             /* 12- 0 */
614
        h->spacing = 1; /* wrong */                 /* 13- 1=proportional, 0-fixed pitch */
615
        h->characterSet = 56; /* wrong */            /* 14- same as symSetCode; =56 if unbound. */
616
        h->pitch = 1024; /* wrong */                   /* 16- PCLT */
617
        h->height = 0;                  /* 18- 0 if TrueType */
618
        h->xHeight = 512; /* wrong */                 /* 20- PCLT */
619
        h->widthType = 0; /* wrong */               /* 22- PCLT */
620
        h->style_lsb = 0; /* wrong */               /* 23- PCLT */
621
        h->strokeWeight = 0; /* wrong */            /* 24- PCLT */
622
        h->typeface_lsb = 0; /* wrong */            /* 25- PCLT */
623
        h->typeface_msb = 0; /* wrong */           /* 26- PCLT */
624
        h->serifStyle = 0; /* wrong */              /* 27- PCLT */
625
        h->quality = 0; /* wrong */                 /* 28- 2 if TrueType */
626
        h->placement = 0; /* wronfg */               /* 29- 0 if TrueType */
627
        h->underlinePosition = 0;       /* 30- 0 */
628
        h->underlineHeight = 0;         /* 31- 0 */
629
        h->textHeight = 102; /* wrong */              /* 32- from OS/2 table in TT font */
630
        h->textWidth = 1024; /* wrong */              /* 34- OS/2 */
631
        h->firstCode = 0;               /* 36- set to 0 if unbound */
632
        h->lastCode = 255; /* wrong */                /* 38- max number of downloadable chars if unbound */
633
        h->pitch_ext = 0;               /* 40- 0 if TrueType */
634
        h->height_ext = 0;              /* 41- 0 if TrueType */
635
        h->capHeight = 1024; /* wrong */               /* 42- PCLT */
636
        h->fontNumber = 0; /* wrong */             /* 44- PCLT */
637
        h->fontName[0] = 0; /* wrong */            /* 48- PCLT */
638
        h->scaleFactor = 1024; /* wrong */             /* 64- head:unitsPerEm */
639
        h->masterUnderlinePosition = 0; /* wrong */ /* 66- post table, or -20% of em */
640
        h->masterUnderlineHeight = 0; /* wrong */   /* 68- post table, or 5% of em */
641
        h->fontScalingTechnology = 1;   /* 70- 1=TrueType; 0=Intellifont */
642
        h->variety = 0;                 /* 71- 0 if TrueType */
643
        memset((LPUB8)h + PCLETTOFONTHDRSIZE, 0 ,8); /* work around bug in PCLswapHdr : it wants format 10 */
644
        /*  fixme : Most fields above being marked "wrong" look unused by UFST.
645
            Need to check for sure.
646
        */
647
        /*  fixme : This code assumes 1-byte alignment for PCLETTO_FHDR structure.
648
            Use PACK_* macros to improve.
649
        */
650
        PCLswapHdr(&r->IFS, (UB8 *)h, 0);
651
        if (ff->is_type1) {
652
            LPUB8 fontdata = (LPUB8)h + PCLETTOFONTHDRSIZE;
653
            pack_pseo_fhdr(r, ff, fontdata);
654
        } else {
655
            LPUB8 pseg = (LPUB8)h + PCLETTOFONTHDRSIZE;
656
            LPUB8 fontdata = pseg + (use_XL_format ? 6 : 4);
657
            if (tt_size > 65000)
658
                return e_unregistered; /* Must not happen because we skept 'glyp', 'loca' and 'cmap'. */
659
            pseg[0] = 'G';
660
            pseg[1] = 'T';
661
	    if (use_XL_format) {
662
		pseg[2] = tt_size >> 24;
663
		pseg[3] = (tt_size >> 16) % 256;
664
		pseg[4] = (tt_size >> 8) % 256;
665
		pseg[5] = tt_size % 256;
666
	    } else {
667
		pseg[2] = tt_size / 256;
668
		pseg[3] = tt_size % 256;
669
	    }
670
            d->tt_font_body_offset = (LPUB8)fontdata - (LPUB8)d;
671
            if (ff->serialize_tt_font(ff, fontdata, tt_size))
672
                return e_invalidfont;
673
            *(fontdata + tt_size    ) = 255;
674
            *(fontdata + tt_size + 1) = 255;
675
            *(fontdata + tt_size + 2) = 0;
676
            *(fontdata + tt_size + 3) = 0;
677
            *(fontdata + tt_size + 4) = 0;
678
            *(fontdata + tt_size + 5) = 0;  /* checksum */
679
        }
680
    }
681
    *return_data = d;
682
    return 0;
683
}
684
 
685
private void prepare_typeface(fapi_ufst_server *r, ufst_common_font_data *d)
686
{   r->fc.format = d->font_type;
687
    r->fc.font_id = d->font_id;
688
    r->fc.font_hdr = (UB8 *)(d + 1);
689
    if (!d->is_disk_font)
690
        r->fc.format |= FC_EXTERN_TYPE;
691
}
692
 
693
private FAPI_retcode get_scaled_font(FAPI_server *server, FAPI_font *ff, int subfont, 
694
         const FAPI_font_scale *font_scale, const char *xlatmap, bool bVertical, FAPI_descendant_code dc)
695
{   fapi_ufst_server *r = If_to_I(server);
696
    FONTCONTEXT *fc = &r->fc;
697
    /*  Note : UFST doesn't provide handles for opened fonts,
698
        but copies FONTCONTEXT to IFSTATE and caches it.
699
        Due to this the plugin cannot provide a handle for the font.
700
        This assumes that only one font context is active at a moment.
701
    */
702
    ufst_common_font_data *d = (ufst_common_font_data *)ff->server_font_data;
703
    const double scale = F_ONE;
704
    double hx, hy, sx, sy;
705
    FAPI_retcode code;
706
    bool use_XL_format = ff->is_mtx_skipped;
707
 
708
    if (ff->is_cid && ff->is_type1 && ff->font_file_path == NULL && 
709
        (dc == FAPI_TOPLEVEL_BEGIN || dc == FAPI_TOPLEVEL_COMPLETE)) {
710
	/* Don't need any processing for the top level font of a non-disk CIDFontType 0. 
711
	   See comment in FAPI_prepare_font.
712
	   Will do with its subfonts individually. 
713
	 */
714
	return 0; 
715
    }
716
    ff->need_decrypt = 1;
717
    if (d == 0) {
718
        if ((code = make_font_data(r, ff->font_file_path, subfont, ff, &d)) != 0)
719
	    return code;
720
        ff->server_font_data = d;
721
        prepare_typeface(r, d);
722
        if (ff->font_file_path != NULL || ff->is_type1) /* such fonts don't use RAW_GLYPH */
723
            choose_decoding(r, d, xlatmap);
724
    } else
725
        prepare_typeface(r, d);
726
    r->tran_xx = font_scale->matrix[0] / scale, r->tran_xy = font_scale->matrix[1] / scale;
727
    r->tran_yx = font_scale->matrix[2] / scale, r->tran_yy = font_scale->matrix[3] / scale;
728
    hx = hypot(r->tran_xx, r->tran_xy), hy = hypot(r->tran_yx, r->tran_yy);
729
    sx = r->tran_xx * r->tran_yx + r->tran_xy * r->tran_yy; 
730
    sy = r->tran_xx * r->tran_yy - r->tran_xy * r->tran_yx;
731
    fc->xspot     = F_ONE;
732
    fc->yspot     = F_ONE;
733
    fc->fc_type   = FC_MAT2_TYPE;
734
    /* Round towards zero for a better view of mirrored characters : */
735
    fc->s.m2.m[0] = (int)((double)font_scale->matrix[0] / hx + 0.5); 
736
    fc->s.m2.m[1] = (int)((double)font_scale->matrix[1] / hx + 0.5);
737
    fc->s.m2.m[2] = (int)((double)font_scale->matrix[2] / hy + 0.5);
738
    fc->s.m2.m[3] = (int)((double)font_scale->matrix[3] / hy + 0.5);
739
    fc->s.m2.matrix_scale = 16;
740
    fc->s.m2.xworld_res = font_scale->HWResolution[0] >> 16;
741
    fc->s.m2.yworld_res = font_scale->HWResolution[1] >> 16;
742
    fc->s.m2.world_scale = 0;
743
    fc->s.m2.point_size   = (int)(hy * 8 + 0.5); /* 1/8ths of pixels */
744
    fc->s.m2.set_size     = (int)(hx * 8 + 0.5);
745
    fc->numXsubpixels = font_scale->subpixels[0];
746
    fc->numYsubpixels = font_scale->subpixels[1];
747
    fc->alignment = (font_scale->align_to_pixels ? GAGG : GAPP);
748
    fc->ssnum = 0x8000; /* no symset mapping */
749
    if (ff->font_file_path == NULL && !ff->is_type1)
750
        fc->ssnum = RAW_GLYPH;
751
    else if (ff->font_file_path != NULL && ff->is_cid) {
752
         if (d->platformId == 3) {
753
            switch (d->specificId) {
754
                case 1 : fc->ssnum = UNICODE;   break;
755
                case 2 : fc->ssnum = SHIFT_JIS; break;
756
                case 3 : fc->ssnum = GB;        break;
757
                case 4 : fc->ssnum = BIG5;      break;
758
                case 5 : fc->ssnum = WANSUNG;   break;
759
                case 6 : fc->ssnum = JOHAB;     break;
760
            }
761
        } else {
762
            /* fixme : other platform IDs */
763
        }
764
    }
765
    fc->format      |= FC_NON_Z_WIND;   /* NON_ZERO Winding required for TrueType */
766
    fc->format      |= FC_INCHES_TYPE;  /* output in units per inch */
767
    fc->user_platID = d->platformId;
768
    fc->user_specID = d->specificId;
769
    fc->ExtndFlags = EF_TT_CMAPTABL;
770
    if (use_XL_format)
771
	fc->ExtndFlags |= EF_XLFONT_TYPE;
772
    if (bVertical)
773
        fc->ExtndFlags |= EF_UFSTVERT_TYPE;
774
    fc->dl_ssnum = (d->specificId << 4) | d->platformId;
775
    fc->ttc_index   = subfont;
776
    r->callback_error = 0;
777
    gx_set_UFST_Callbacks(gs_PCLEO_charptr, gs_PCLchId2ptr, gs_PCLglyphID2Ptr);
778
    code = CGIFfont(&r->IFS, fc);
779
    if (r->callback_error != 0)
780
	return r->callback_error;
781
    return code;
782
}
783
 
784
private FAPI_retcode get_decodingID(FAPI_server *server, FAPI_font *ff, const char **decodingID_result)
785
{   fapi_ufst_server *r = If_to_I(server);
786
    ufst_common_font_data *d = (ufst_common_font_data *)r->fc.font_hdr - 1;
787
 
788
    *decodingID_result = d->decodingID;
789
    return 0;
790
}
791
 
792
private FAPI_retcode get_font_bbox(FAPI_server *server, FAPI_font *ff, int BBox[4])
793
{   fapi_ufst_server *r = If_to_I(server);
794
    SW16 VLCPower = 0;
795
    int code;
796
 
797
    if ((code = CGIFbound_box(&r->IFS, BBox, &VLCPower)) < 0)
798
	return code;
799
    /*  UFST expands bbox for internal needs, and retrives the expanded bbox.
800
        We believe it's bug in UFST.
801
        Now we collapse it back to the correct size :
802
    */
803
    BBox[0] += 2;
804
    BBox[1] += 2;
805
    BBox[2] -= 2;
806
    BBox[3] -= 2;
807
    BBox[0] >>= VLCPower;
808
    BBox[1] >>= VLCPower;
809
    BBox[2] >>= VLCPower;
810
    BBox[3] >>= VLCPower;
811
    return 0;
812
}
813
 
814
private FAPI_retcode get_font_proportional_feature(FAPI_server *server, FAPI_font *ff, int subfont, bool *bProportional)
815
{   fapi_ufst_server *r = If_to_I(server);
816
    UB8 buf[74];
817
    UL32 length = sizeof(buf);
818
    *bProportional = false;
819
 
820
    if (ff->font_file_path == NULL || ff->is_type1)
821
        return 0;
822
    if (CGIFtt_query(&r->IFS, (UB8 *)ff->font_file_path, *(UL32 *)"OS/2", (UW16)subfont, &length, buf) != 0)
823
        return 0; /* No OS/2 table - no chance to get the info. Use default == false. */
824
    *bProportional = (buf[35] == 9);
825
    return 0;
826
}
827
 
828
private inline void make_asciiz_char_name(char *buf, int buf_length, FAPI_char_ref *c)
829
{   int len = min(buf_length - 1, c->char_name_length);
830
 
831
    memcpy(buf, c->char_name, len);
832
    buf[len] = 0;
833
}
834
 
835
#define MAX_CHAR_NAME_LENGTH 30
836
 
837
private FAPI_retcode can_retrieve_char_by_name(FAPI_server *server, FAPI_font *ff, FAPI_char_ref *c, int *result)
838
{   fapi_ufst_server *r = If_to_I(server);
839
 
840
    *result = 0;
841
    switch (r->fc.format & FC_FONTTYPE_MASK) {
842
        case FC_PST1_TYPE : 
843
            *result = 1; 
844
            break;
845
        case FC_TT_TYPE : 
846
#if 0 /* Doesn't work because Agfa can't retrive characters by name. 
847
                     It wants a char code together with the name. */
848
                if (ff->font_file_path != NULL) {
849
                    UB8 buf[2];
850
                    UL32 l = sizeof(buf);
851
                    UW16 code = CGIFtt_query(&r->IFS, r->fc.font_hdr, tag_Postscript, r->fc.ttc_index, &l, buf);
852
                    *result = (code == 0);
853
                }
854
#endif
855
            break;
856
    }
857
    return 0;
858
}
859
 
860
private FAPI_retcode can_replace_metrics(FAPI_server *server, FAPI_font *ff, FAPI_char_ref *c, int *result)
861
{   *result = (!ff->is_type1 && ff->font_file_path == NULL &&
862
	       c->metrics_scale == 0 && c->metrics_type == FAPI_METRICS_REPLACE);
863
    return 0;
864
}
865
 
866
private void release_glyphs(fapi_ufst_server *r, ufst_common_font_data *d)
867
{   while (d->glyphs != 0) {
868
        pcleo_glyph_list_elem *e = d->glyphs;
869
        d->glyphs = e->next;
870
        r->client_mem.free(&r->client_mem, e, "PCLEO char");
871
    }
872
}
873
 
874
private FAPI_retcode get_char_width(FAPI_server *server, FAPI_font *ff, FAPI_char_ref *c, FAPI_metrics *metrics)
875
{   fapi_ufst_server *r = If_to_I(server);
876
    UW16 buffer[2];
877
    UW16 cc = (UW16)c->char_code;
878
    char PSchar_name[MAX_CHAR_NAME_LENGTH];
879
    int code;
880
 
881
    make_asciiz_char_name(PSchar_name, sizeof(PSchar_name), c);
882
    r->ff = ff;
883
    CGIFchIdptr(&r->IFS, &cc, PSchar_name);
884
    if ((code = CGIFwidth(&r->IFS, cc, 1, 4, buffer)) != 0)
885
	return code;
886
    r->ff = 0;
887
    release_glyphs(r, (ufst_common_font_data *)ff->server_font_data);
888
    metrics->escapement = buffer[0];
889
    metrics->em_x = metrics->em_y = buffer[1];
890
    return 0;
891
}
892
 
893
private int export_outline(fapi_ufst_server *r, PIFOUTLINE pol, FAPI_path *p)
894
{   POUTLINE_CHAR outchar;
895
    SW16 num_contrs,num_segmts;
896
    LPSB8 segment;
897
    PINTRVECTOR points;
898
    SW16  i,j;
899
 
900
    if (pol == NULL)
901
        return 0;
902
    p->shift += r->If.frac_shift + pol->VLCpower;
903
    outchar = &pol->ol;
904
    num_contrs = outchar->num_loops;
905
    for(i=0; i<num_contrs; i++) {
906
     	num_segmts = outchar->loop[i].num_segmts;
907
        segment = (LPSB8)((LPSB8)(outchar->loop) + outchar->loop[i].segmt_offset);
908
        points = (PINTRVECTOR)((LPSB8)(outchar->loop) + outchar->loop[i].coord_offset);
909
        for(j=0; j<num_segmts; j++) {
910
	    int code;
911
 
912
            if(*segment == 0x00) {
913
             	if ((code = p->moveto(p, points->x, points->y)) != 0)
914
		    return code;
915
                points++;
916
            } else if (*segment == 0x01) {
917
		if ((code = p->lineto(p, points->x, points->y)) != 0)
918
		    return code;
919
                points++;
920
            } else if (*segment == 0x02) {
921
                points+=2;
922
                return e_invalidfont; /* This must not happen */
923
            } else if (*segment == 0x03) {
924
		if ((code = p->curveto(p, points[0].x, points[0].y,
925
					points[1].x, points[1].y,
926
					points[2].x, points[2].y)) < 0)
927
		    return code;
928
                points+=3;
929
            } else
930
                return e_invalidfont; /* This must not happen */
931
            segment++;
932
        }
933
    }
934
    return 0;
935
}
936
 
937
private inline void set_metrics(fapi_ufst_server *r, FAPI_metrics *metrics, SL32 design_bbox[4], SW16 design_escapement, int escapement, SW16 du_emx, SW16 du_emy)
938
{   metrics->escapement = design_escapement; 
939
    metrics->em_x = du_emx;
940
    metrics->em_y = du_emy;
941
    metrics->bbox_x0 = design_bbox[0];
942
    metrics->bbox_y0 = design_bbox[1];
943
    metrics->bbox_x1 = design_bbox[2];
944
    metrics->bbox_y1 = design_bbox[3];
945
}
946
 
947
private FAPI_retcode get_char(fapi_ufst_server *r, FAPI_font *ff, FAPI_char_ref *c, FAPI_path *p, FAPI_metrics *metrics, UW16 format)
948
{   UW16 code;
949
    UW16 cc = (UW16)c->char_code;
950
    SL32 design_bbox[4];
951
    SW16 design_escapement;
952
    char PSchar_name[MAX_CHAR_NAME_LENGTH];
953
    MEM_HANDLE result;
954
 
955
    memset(metrics, 0, sizeof(*metrics));
956
    metrics->bbox_x1 = -1;
957
    make_asciiz_char_name(PSchar_name, sizeof(PSchar_name), c);
958
    CGIFchIdptr(&r->IFS, &cc, PSchar_name);
959
    {   /* hack : Changing UFST internal data. Change to r->fc doesn't help, because Agfa thinks that the "outline/raster" is a property of current font. */
960
        r->IFS.fcCur.format &= ~FC_OUTPUT_MASK;
961
        r->IFS.fcCur.format |= format;
962
    }
963
    r->bRaster = false;
964
    r->ff = ff;
965
    r->callback_error = 0;
966
    r->sb_x = c->sb_x;
967
    r->aw_x = c->aw_x;
968
    r->metrics_type = c->metrics_type;
969
    code = CGIFchar_with_design_bbox(&r->IFS, cc, &result, (SW16)0, design_bbox, &design_escapement);
970
    if (code == ERR_find_cgnum) {
971
        /* There is no such char in the font, try the glyph 0 (notdef) : */
972
        const void *client_char_data = ff->char_data;
973
        UW16 c1 = 0, ssnum = r->IFS.fcCur.ssnum;
974
        /* hack : Changing UFST internal data - see above. */
975
        r->IFS.fcCur.ssnum = RAW_GLYPH;
976
        r->callback_error = 0;
977
        ff->char_data = NULL;
978
        CGIFchIdptr(&r->IFS, &c1, (char *)".notdef");
979
        code = CGIFchar_with_design_bbox(&r->IFS, c1, &result, (SW16)0, design_bbox, &design_escapement);
980
        r->IFS.fcCur.ssnum = ssnum;
981
        ff->char_data = client_char_data;
982
    }
983
    r->ff = 0;
984
    release_glyphs(r, (ufst_common_font_data *)ff->server_font_data);
985
    if (code != ERR_fixed_space && code != 0)
986
	return code;
987
    if (r->callback_error != 0)
988
	return r->callback_error;
989
    if (format == FC_BITMAP_TYPE) {
990
        IFBITMAP *pbm = (IFBITMAP *)result;
991
        set_metrics(r, metrics, design_bbox, design_escapement, pbm->escapement, pbm->du_emx, pbm->du_emy);
992
        r->char_data = pbm;
993
        r->bRaster = true;
994
    } else {
995
        IFOUTLINE *pol = (IFOUTLINE *)result;
996
        set_metrics(r, metrics, design_bbox, design_escapement, pol->escapement, pol->du_emx, pol->du_emy);
997
        r->char_data = (IFOUTLINE *)result;
998
    }
999
    if (code == ERR_fixed_space)
1000
        release_char_data_inline(r);
1001
    return 0;
1002
}
1003
 
1004
private FAPI_retcode get_char_outline_metrics(FAPI_server *server, FAPI_font *ff, FAPI_char_ref *c, FAPI_metrics *metrics)
1005
{   fapi_ufst_server *r = If_to_I(server);
1006
 
1007
    release_char_data_inline(r);
1008
    return get_char(r, ff, c, NULL, metrics, FC_CUBIC_TYPE);
1009
    /*	UFST cannot render enough metrics information without generating raster or outline. 
1010
	r->char_data keeps an outline after calling this function.
1011
    */
1012
}
1013
 
1014
private FAPI_retcode get_char_outline(FAPI_server *server, FAPI_path *p)
1015
{   fapi_ufst_server *r = If_to_I(server);
1016
 
1017
    return export_outline(r, (IFOUTLINE *)r->char_data, p);
1018
}
1019
 
1020
private FAPI_retcode get_char_raster_metrics(FAPI_server *server, FAPI_font *ff, FAPI_char_ref *c, FAPI_metrics *metrics)
1021
{   fapi_ufst_server *r = If_to_I(server);
1022
    int code;
1023
 
1024
    release_char_data_inline(r);
1025
    code = get_char(r, ff, c, NULL, metrics, FC_BITMAP_TYPE);
1026
    if (code == ERR_bm_buff || code == ERR_bm_too_big) /* Too big character ? */
1027
        return e_limitcheck;
1028
    return code;
1029
    /*	UFST cannot render enough metrics information without generating raster or outline. 
1030
	r->char_data keeps a raster after calling this function.
1031
    */
1032
}
1033
 
1034
private FAPI_retcode get_char_raster(FAPI_server *server, FAPI_raster *rast)
1035
{   fapi_ufst_server *r = If_to_I(server);
1036
 
1037
    if (!r->bRaster)
1038
        return e_limitcheck;
1039
    else if (r->char_data == NULL) {
1040
	rast->height = rast->width = rast->line_step = 0;
1041
	rast->p = 0;
1042
    } else {
1043
        IFBITMAP *pbm = (IFBITMAP *)r->char_data;
1044
        rast->p = pbm->bm;
1045
        rast->height = pbm->depth;
1046
        rast->width = pbm->width << CHUNK_SHIFT;
1047
        rast->line_step = (pbm->width + (1 << (CHUNK_SHIFT - 3)) - 1) >> (CHUNK_SHIFT - 3);
1048
        if (rast->width != 0) {
1049
            rast->orig_x = pbm->left_indent * 16 + pbm->xorigin;
1050
            rast->orig_y = pbm->top_indent  * 16 + pbm->yorigin;
1051
        } else
1052
            rast->orig_x = rast->orig_y = 0;
1053
    }
1054
    return 0;
1055
}
1056
 
1057
private FAPI_retcode release_char_data(FAPI_server *server)
1058
{   fapi_ufst_server *r = If_to_I(server);
1059
 
1060
    release_char_data_inline(r);
1061
    return 0;
1062
}
1063
 
1064
private void release_fco(fapi_ufst_server *r, SW16 fcHandle)
1065
{   fco_list_elem **e = &r->fco_list;
1066
 
1067
    for (; *e != 0; )
1068
        if ((*e)->fcHandle == fcHandle && (--(*e)->open_count) == 0) {
1069
            fco_list_elem *ee = *e;
1070
            *e = ee->next;
1071
            CGIFfco_Close(&r->IFS, ee->fcHandle);
1072
            r->client_mem.free(&r->client_mem, ee->file_path, "fco_file_path");
1073
            r->client_mem.free(&r->client_mem, ee, "fco_list_elem");
1074
        } else
1075
            e = &(*e)->next;
1076
}
1077
 
1078
private FAPI_retcode release_typeface(FAPI_server *server, void *font_data)
1079
{   fapi_ufst_server *r = If_to_I(server);
1080
    ufst_common_font_data *d;
1081
    FAPI_retcode code = 0;
1082
 
1083
    release_char_data_inline(r);
1084
    if (font_data == 0)
1085
        return 0;
1086
    d = (ufst_common_font_data *)font_data;
1087
    prepare_typeface(r, d);
1088
    if (d->is_disk_font)
1089
        code = CGIFhdr_font_purge(&r->IFS, &r->fc);
1090
    else
1091
        code = CGIFfont_purge(&r->IFS, &r->fc);
1092
    release_glyphs(r, d);
1093
    release_fco(r, (SW16)(d->font_id >> 16));
1094
    r->client_mem.free(&r->client_mem, font_data, "ufst font data");
1095
    return code;
1096
}
1097
 
1098
/* --------------------- The plugin definition : ------------------------- */
1099
 
1100
 
1101
private void gs_fapiufst_finit(i_plugin_instance *instance, i_plugin_client_memory *mem);
1102
 
1103
private const i_plugin_descriptor ufst_descriptor = {
1104
    "FAPI",
1105
    "AgfaUFST",
1106
    gs_fapiufst_finit
1107
};
1108
 
1109
private const FAPI_server If0 = {
1110
    {   &ufst_descriptor
1111
    },
1112
    16, /* frac_shift */
1113
    ensure_open,
1114
    get_scaled_font,
1115
    get_decodingID,
1116
    get_font_bbox,
1117
    get_font_proportional_feature,
1118
    can_retrieve_char_by_name,
1119
    can_replace_metrics,
1120
    get_char_width,
1121
    get_char_raster_metrics,
1122
    get_char_raster,
1123
    get_char_outline_metrics,
1124
    get_char_outline,
1125
    release_char_data,
1126
    release_typeface
1127
};
1128
 
1129
plugin_instantiation_proc(gs_fapiufst_instantiate);      /* check prototype */
1130
 
1131
int gs_fapiufst_instantiate(i_ctx_t *i_ctx_p, i_plugin_client_memory *client_mem, i_plugin_instance **p_instance)
1132
{   fapi_ufst_server *r = (fapi_ufst_server *)client_mem->alloc(client_mem, sizeof(fapi_ufst_server), "fapi_ufst_server");
1133
 
1134
    if (r == 0)
1135
        return e_Fatal;
1136
    memset(r, 0, sizeof(*r));
1137
    r->If = If0;
1138
    r->client_mem = *client_mem;
1139
    *p_instance = &r->If.ig;
1140
    return 0;
1141
}
1142
 
1143
private void gs_fapiufst_finit(i_plugin_instance *this, i_plugin_client_memory *mem)
1144
{   fapi_ufst_server *r = (fapi_ufst_server *)this;
1145
 
1146
    if (r->If.ig.d != &ufst_descriptor)
1147
        return; /* safety */
1148
    release_char_data_inline(r);
1149
    if (r->bInitialized) {
1150
        CGIFexit(&r->IFS);
1151
    }
1152
    mem->free(mem, r, "fapi_ufst_server");
1153
}
1154