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
If_to_I(FAPI_server * If)96 private inline fapi_ufst_server *If_to_I(FAPI_server *If)
97 { return (fapi_ufst_server *)If;
98 }
99
IFS_to_I(IF_STATE * pIFS)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
release_char_data_inline(fapi_ufst_server * r)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
open_UFST(fapi_ufst_server * r)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
ensure_open(FAPI_server * server)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
get_font_type(FILE * f)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
choose_decoding_PS(fapi_ufst_server * r,ufst_common_font_data * d,const char * cmapId)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
choose_decoding_TT(fapi_ufst_server * r,ufst_common_font_data * d,const char * cmapId)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
scan_xlatmap(fapi_ufst_server * r,ufst_common_font_data * d,const char * xlatmap,const char * font_kind,int (* choose_proc)(fapi_ufst_server * r,ufst_common_font_data * d,const char * cmapId))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
choose_decoding(fapi_ufst_server * r,ufst_common_font_data * d,const char * xlatmap)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
store_word(byte ** p,ushort w)231 private inline void store_word(byte **p, ushort w)
232 { *((*p)++) = w / 256;
233 *((*p)++) = w % 256;
234
235 }
236
get_TT_glyph(fapi_ufst_server * r,FAPI_font * ff,UW16 chId)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
get_T1_glyph(fapi_ufst_server * r,FAPI_font * ff,UW16 chId)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
find_glyph(ufst_common_font_data * d,UW16 chId)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
gs_PCLEO_charptr(LPUB8 pfont_hdr,UW16 sym_code)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
gs_PCLchId2ptr(IF_STATE * pIFS,UW16 chId)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
gs_PCLglyphID2Ptr(IF_STATE * pIFS,UW16 glyphID)374 private LPUB8 gs_PCLglyphID2Ptr(IF_STATE *pIFS, UW16 glyphID)
375 { return gs_PCLchId2ptr(pIFS, glyphID);
376 }
377
pack_word(LPUB8 * p,UW16 v)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
pack_long(LPUB8 * p,UL32 v)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
pack_float(LPUB8 * p,float v)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
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)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
pack_pseo_fhdr(fapi_ufst_server * r,FAPI_font * ff,UB8 * p)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
enumerate_fco(fapi_ufst_server * r,const char * font_file_path)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
my_strdup(fapi_ufst_server * r,const char * s,const char * cname)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
fco_open(fapi_ufst_server * r,const char * font_file_path,fco_list_elem ** result)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
make_font_data(fapi_ufst_server * r,const char * font_file_path,int subfont,FAPI_font * ff,ufst_common_font_data ** return_data)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
prepare_typeface(fapi_ufst_server * r,ufst_common_font_data * d)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
get_scaled_font(FAPI_server * server,FAPI_font * ff,int subfont,const FAPI_font_scale * font_scale,const char * xlatmap,bool bVertical,FAPI_descendant_code dc)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
get_decodingID(FAPI_server * server,FAPI_font * ff,const char ** decodingID_result)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
get_font_bbox(FAPI_server * server,FAPI_font * ff,int BBox[4])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
get_font_proportional_feature(FAPI_server * server,FAPI_font * ff,int subfont,bool * bProportional)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
make_asciiz_char_name(char * buf,int buf_length,FAPI_char_ref * c)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
can_retrieve_char_by_name(FAPI_server * server,FAPI_font * ff,FAPI_char_ref * c,int * result)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
can_replace_metrics(FAPI_server * server,FAPI_font * ff,FAPI_char_ref * c,int * result)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
release_glyphs(fapi_ufst_server * r,ufst_common_font_data * d)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
get_char_width(FAPI_server * server,FAPI_font * ff,FAPI_char_ref * c,FAPI_metrics * metrics)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
export_outline(fapi_ufst_server * r,PIFOUTLINE pol,FAPI_path * p)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
set_metrics(fapi_ufst_server * r,FAPI_metrics * metrics,SL32 design_bbox[4],SW16 design_escapement,int escapement,SW16 du_emx,SW16 du_emy)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
get_char(fapi_ufst_server * r,FAPI_font * ff,FAPI_char_ref * c,FAPI_path * p,FAPI_metrics * metrics,UW16 format)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
get_char_outline_metrics(FAPI_server * server,FAPI_font * ff,FAPI_char_ref * c,FAPI_metrics * metrics)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
get_char_outline(FAPI_server * server,FAPI_path * p)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
get_char_raster_metrics(FAPI_server * server,FAPI_font * ff,FAPI_char_ref * c,FAPI_metrics * metrics)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
get_char_raster(FAPI_server * server,FAPI_raster * rast)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
release_char_data(FAPI_server * server)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
release_fco(fapi_ufst_server * r,SW16 fcHandle)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
release_typeface(FAPI_server * server,void * font_data)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
gs_fapiufst_instantiate(i_ctx_t * i_ctx_p,i_plugin_client_memory * client_mem,i_plugin_instance ** p_instance)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
gs_fapiufst_finit(i_plugin_instance * this,i_plugin_client_memory * mem)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
1155