1 /* Copyright (C) 2001-2012 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., 7 Mt. Lassen Drive - Suite A-134, San Rafael,
13 CA 94903, U.S.A., +1(415)492-9861, for further information.
14 */
15
16
17 /* Agfa UFST plugin */
18
19 /* GS includes : */
20 #include "stdio_.h"
21 #include "stream.h"
22 #include "strmio.h"
23
24 #include "memory_.h"
25 #include "gsmemory.h"
26 #include "math_.h"
27 #include "stat_.h" /* include before definition of esp macro, bug 691123 */
28 #include "ghost.h"
29 #include "gp.h"
30 #include "oper.h"
31 #include "gxdevice.h"
32 #include "gxfont.h"
33 #include "gxfont1.h"
34 #include "gxchar.h"
35 #include "gxpath.h"
36 #include "gxfcache.h"
37 #include "gxchrout.h"
38 #include "gximask.h"
39 #include "gscoord.h"
40 #include "gspaint.h"
41 #include "gsfont.h"
42 #include "gspath.h"
43 #include "bfont.h"
44 #include "dstack.h"
45 #include "estack.h"
46 #include "ichar.h"
47 #include "idict.h"
48 #include "iname.h"
49 #include "ifont.h"
50 #include "icid.h"
51 #include "igstate.h"
52 #include "icharout.h"
53 #include "ifapi.h"
54 #include "iplugin.h"
55 #include "store.h"
56 #include "gzstate.h"
57 #include "gdevpsf.h"
58 #include "stream.h" /* for files.h */
59 #include "gscrypt1.h"
60 #include "gxfcid.h"
61 #include "gsstype.h"
62 #include "gxchar.h" /* for st_gs_show_enum */
63 #include "ipacked.h" /* for packed_next */
64 #include "iddict.h"
65 #include "ifont42.h" /* for string_array_access_proc */
66 #include "gsmalloc.h"
67 #include "gsmchunk.h"
68
69 #undef frac_bits
70
71 #ifndef _MSC_VER
72 #define _MSC_VER 0
73 #endif
74
75 /* UFST includes : */
76 #include "cgconfig.h"
77 #include "ufstport.h"
78 #include "dbg_ufst.h"
79 #include "shareinc.h"
80 #include "t1isfnt.h"
81 #include "cgmacros.h"
82 #include "sfntenum.h"
83 #define DOES_ANYONE_USE_THIS_STRUCTURE /* see TTPCLEO.H, UFST 4.2 */
84 #include "ttpcleo.h"
85 #undef DOES_ANYONE_USE_THIS_STRUCTURE
86 #include "gxfapiu.h"
87
88 /* more gs includes */
89 #include "iref.h"
90 #include "ialloc.h"
91 #include "imemory.h"
92 #include "iname.h"
93 #include "iapi.h"
94 #include "iminst.h"
95 #include "imain.h"
96 #include "igstate.h"
97 #include "idict.h"
98 #include "dstack.h"
99 #include "store.h"
100
101 #if UFST_VERSION_MAJOR >= 6 && UFST_VERSION_MINOR >= 2
102 #include "t1itype1.h"
103 #endif
104
105 #if UFST_VERSION_MAJOR >= 6 && UFST_VERSION_MINOR >= 2
106 #undef true
107 #undef false
108
109 #define false FALSE
110 #define true TRUE
111 #define UNICODE UFST_UNICODE
112 #endif
113
114 #ifndef UFSTFONTDIR
115 #define UFSTFONTDIR ""
116 #endif
117
118 #define UFST_PlugIn_Str "UFST_PlugIn"
119 #define UFST_PlugIn_Path "mtfonts/pcl45/mt3/plug__xi.fco"
120
121 #define FCOfontfilePath "mtfonts/pclps2/mt3/pclp2_xj.fco"
122 #define FCOfontfileStr "FCOfontfile"
123
124 #define FCOfontfile2Str "FCOfontfile2"
125 #define FCOfontfile2Path "mtfonts/pcl45/mt3/wd____xh.fco"
126
127 #define FAPIfontmapStr "FAPIfontmap"
128 #define FAPIfontmap "FCOfontmap-PCLPS2"
129
130 /* Prior to 6.2, prototypes had empty parameter lists, causing problems
131 * when passing 64 bit pointers into the UFST functions.
132 * Prototype "properly" here.
133 */
134 #if UFST_VERSION_MAJOR < 6
135 #if defined (ANSI_DEFS)
136 UW16 CGENTRY CGIFFfont (FSP PFONTCONTEXT fc);
137 #else
138 UW16 CGENTRY CGIFFfont (fc);
139 PFONTCONTEXT fc;
140 #endif /* ANSI_DEFS */
141 #endif
142
143 typedef struct fapi_ufst_server_s fapi_ufst_server;
144
145 static unsigned int font_ids = 0x7fffffff;
146
147 #if UFST_REENTRANT
148 #define FSA_FROM_SERVER IF_STATE *pIFS = &r->IFS
149 #else
150 EXTERN IF_STATE if_state;
151 #define FSA_FROM_SERVER IF_STATE *pIFS = &if_state; (void)r; (void)pIFS;
152 static fapi_ufst_server *static_server_ptr_for_ufst_callback = 0;
153 #endif
154
155 GLOBAL UW16 PCLswapHdr( FSP LPUB8 p, UW16 gifct ); /* UFST header doesn't define it. */
156
157 typedef struct pcleo_glyph_list_elem_s pcleo_glyph_list_elem;
158 struct pcleo_glyph_list_elem_s {
159 UW16 chId;
160 pcleo_glyph_list_elem *next;
161 /* more data follows here depending on font type */
162 };
163
164 typedef struct {
165 SL32 font_id;
166 uint tt_font_body_offset;
167 UW16 is_disk_font;
168 UW16 font_type;
169 UW16 platformId;
170 UW16 specificId;
171 pcleo_glyph_list_elem *glyphs;
172 char decodingID[40];
173 } ufst_common_font_data;
174
175 typedef struct {
176 PCLETTO_CHR_HDR h;
177 UW16 add_data;
178 UW16 charDataSize;
179 UW16 glyphID;
180 } PCLETTO_CHDR;
181
182 struct fapi_ufst_server_s {
183 FAPI_server If;
184 int bInitialized;
185 FAPI_font *ff;
186 gs_memory_t *mem;
187 byte *param;
188 int param_size;
189 IF_STATE IFS;
190 FONTCONTEXT fc;
191 void *char_data;
192 bool bRaster;
193 bool ufst_is_singleton;
194 double tran_xx, tran_xy, tran_yx, tran_yy;
195 fco_list_elem *fco_list;
196 FAPI_retcode callback_error;
197 FAPI_metrics_type metrics_type;
198 FracInt sb_x, aw_x; /* replaced PS metrics. */
199 };
200
201 static inline void release_char_data_inline(fapi_ufst_server *r);
202 static void release_glyphs(fapi_ufst_server *r, ufst_common_font_data *d);
203
204 /* Type casts : */
205
If_to_I(FAPI_server * If)206 static inline fapi_ufst_server *If_to_I(FAPI_server *If)
207 { return (fapi_ufst_server *)If;
208 }
209
IFS_to_I(IF_STATE * pIFS)210 static inline fapi_ufst_server *IFS_to_I(IF_STATE *pIFS)
211 { return (fapi_ufst_server *)((char *)pIFS - offset_of(fapi_ufst_server, IFS));
212 }
213
214 /* assign font_id not based on fchandle value, nor read from font */
assign_font_id(void)215 static inline int assign_font_id(void)
216 {
217 /* We're only allowed 5 open FCOs at one time
218 * so make sure we don't clash with those
219 */
220 if ((--font_ids) <= (5 << 16)) {
221 /* When we clash with the expected values for FCO's
222 * wrap around. No will ever have enough concurrent
223 * fonts for this to be a problem!
224 */
225 font_ids = 0x7fffffff;
226 }
227 return(font_ids);
228 }
229
230 /*------------------ FAPI_server members ------------------------------------*/
231
release_char_data_inline(fapi_ufst_server * r)232 static inline void release_char_data_inline(fapi_ufst_server *r)
233 { /* The server keeps character raster between calls to get_char_raster_metrics
234 and get_char_raster, as well as between calls to get_char_outline_metrics
235 and get_char_outline. Meanwhile this regular
236 sequence of calls may be interrupted by an error in CDefProc or setchachedevice2,
237 which may be invoked between them. In this case Ghostscript
238 is unable to provide a signal to FAPI that the data are not
239 longer needed. This would cause memory leaks in UFST heap.
240 To work around this, appropriate server's entries check whether
241 raster data were left after a previous call, and ultimately release them.
242 This function provides it.
243 */
244 if (r->char_data != NULL) {
245 FSA_FROM_SERVER;
246
247 CHARfree(FSA (MEM_HANDLE)r->char_data);
248 r->char_data = 0;
249 }
250 }
251
252 /*
253 * In the language switch build (which we detect because PSI_INCLUDED
254 * is defined), we use the gx_UFST_init() call to initialize the UFST,
255 * rather than calling into the UFST directly. That has the advantage
256 * that the same UFST configuration is used for PCL and PS, but the
257 * disadvantage that the dynamic parameters set in server_param are
258 * not available. Thus, it is switched through this compile time option.
259 */
open_UFST(fapi_ufst_server * r,const byte * server_param,int server_param_size)260 static FAPI_retcode open_UFST(fapi_ufst_server *r, const byte *server_param, int server_param_size)
261 {
262 int code;
263 SW16 fcHandle;
264 int l;
265 char ufst_root_dir[1024] = "";
266 char sPlugIn[1024] = "";
267 bool bSSdir = FALSE, bPlugIn = FALSE;
268 const char *keySSdir = "UFST_SSdir=";
269 const int keySSdir_length = strlen(keySSdir);
270 const char *keyPlugIn = "UFST_PlugIn=";
271 const int keyPlugIn_length = strlen(keyPlugIn);
272 const char sep = gp_file_name_list_separator;
273 const byte *p = server_param, *e = server_param + server_param_size, *q;
274 FSA_FROM_SERVER;
275
276 if (server_param_size > 0 && server_param) {
277 r->param = (byte *)gs_malloc(r->mem, server_param_size, 1, "server_params");
278 if (!r->param) {
279 return_error (e_VMerror);
280 }
281 memcpy(r->param, server_param, server_param_size);
282 r->param_size = server_param_size;
283 }
284
285 for (; p < e ; p = q + 1) {
286 for (q = p; q < e && *q != sep; q++)
287 /* DO_NOTHING */;
288 l = q - p;
289 if (l > keySSdir_length && !memcmp(p, keySSdir, keySSdir_length)) {
290 l = q - p - keySSdir_length;
291 if (l > sizeof(ufst_root_dir) - 1)
292 l = sizeof(ufst_root_dir) - 1;
293 memcpy(ufst_root_dir, p + keySSdir_length, l);
294 ufst_root_dir[l] = 0;
295 bSSdir = TRUE;
296 } else if (l > keyPlugIn_length && !memcmp(p, keyPlugIn, keyPlugIn_length)) {
297 l = q - p - keyPlugIn_length;
298 if (l > sizeof(sPlugIn) - 1)
299 l = sizeof(sPlugIn) - 1;
300 memcpy(sPlugIn, p + keyPlugIn_length, l);
301 sPlugIn[l] = 0;
302 bPlugIn = TRUE;
303 } else
304 emprintf(r->mem,
305 "Warning: Unknown UFST parameter ignored.\n");
306 }
307 #if !NO_SYMSET_MAPPING
308 if (!bSSdir) {
309 strcpy(ufst_root_dir, ".");
310 emprintf(r->mem,
311 "Warning: UFST_SSdir is not specified, will search *.ss files in the curent directory.\n");
312 }
313 #endif
314 code = gx_UFST_init(r->mem, (const UB8 *)ufst_root_dir);
315 if (code < 0)
316 return code;
317 r->ufst_is_singleton = (code == 1);
318 CGIFfont_access (FSA DISK_ACCESS);
319 if (bPlugIn) {
320 if ((code = gx_UFST_open_static_fco(sPlugIn, &fcHandle)) != 0)
321 return code;
322 if ((code = CGIFfco_Plugin(FSA fcHandle)) != 0)
323 return code;
324 } else {
325 #ifdef FCO_RDR
326 emprintf(r->mem,
327 "Warning: UFST_PlugIn is not specified, some characters may be missing.\n");
328 #endif
329 }
330 return 0;
331 }
332
333 static LPUB8 impl_PCLchId2ptr(FSP UW16 chId);
334
ensure_open(FAPI_server * server,const byte * server_param,int server_param_size)335 static FAPI_retcode ensure_open(FAPI_server *server, const byte *server_param, int server_param_size)
336 { fapi_ufst_server *r = If_to_I(server);
337 int code;
338
339 if (r->bInitialized)
340 return 0;
341 r->bInitialized = 1;
342 {
343 code = open_UFST(r, server_param, server_param_size);
344 if (code < 0) {
345 emprintf(r->mem, "Error opening the UFST font server.\n");
346 return code;
347 }
348 }
349 gx_set_UFST_Callbacks(NULL, impl_PCLchId2ptr, impl_PCLchId2ptr);
350 return 0;
351 }
352
get_font_type(stream * f)353 static UW16 get_font_type(stream *f)
354 { char buf[20], mark_PS[]="%!";
355 int i;
356
357 if (sfread(buf, 1, sizeof(buf), f) != sizeof(buf))
358 return 0;
359 if (buf[0] == 0x15 || buf[0] == 0x00) /* fixme : don't know how to do correctly. */
360 return FC_FCO_TYPE;
361 for (i = 0; i < sizeof(buf) - sizeof(mark_PS); i++)
362 if(!memcmp(buf + i, mark_PS, sizeof(mark_PS) - 1))
363 return FC_PST1_TYPE;
364 if (buf[0] == '\0' && buf[1] == '\1')
365 return FC_TT_TYPE;
366 if (buf[0] == 't' && buf[1] == 't')
367 return FC_TT_TYPE;
368 return 0; /* fixme : unknown type - actually an error. */
369 }
370
choose_decoding_general(fapi_ufst_server * r,ufst_common_font_data * d,const char * cmapId)371 static int choose_decoding_general(fapi_ufst_server *r, ufst_common_font_data *d, const char *cmapId)
372 {
373 if (!d->decodingID[0])
374 strncpy(d->decodingID, "Unicode", sizeof(d->decodingID));
375 /* fixme : must depend on charset used in the font. */
376 return 1;
377 }
378
choose_decoding_TT(fapi_ufst_server * r,ufst_common_font_data * d,const char * cmapId)379 static int choose_decoding_TT(fapi_ufst_server *r, ufst_common_font_data *d, const char *cmapId)
380 {
381 #if TT_ROM || TT_DISK
382 int platId, specId, i;
383 CMAP_QUERY q;
384 UW16 font_access;
385 bool failed;
386 void *p = (d->is_disk_font ? (void *)(d + 1) : (void *)((UB8 *)d + d->tt_font_body_offset));
387 FSA_FROM_SERVER;
388
389 if (sscanf(cmapId, "%d.%d", &platId, &specId) != 2)
390 return 0;
391 font_access = pIFS->font_access;
392 pIFS->font_access = (d->is_disk_font ? DISK_ACCESS : ROM_ACCESS);
393 failed = CGIFtt_cmap_query(FSA p, r->fc.ttc_index, &q);
394 pIFS->font_access = font_access;
395 if(failed)
396 return 0;
397 for (i = 0; i < q.numCmap; i++)
398 if (q.entry[i].platId == platId && q.entry[i].specId == specId) {
399 d->platformId = platId;
400 d->specificId = specId;
401 return 1;
402 }
403 return 0;
404 #else
405 if (!d->decodingID[0])
406 strncpy(d->decodingID, "Unicode", sizeof(d->decodingID));
407 return 1;
408 #endif
409 }
410
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))411 static void scan_xlatmap(fapi_ufst_server *r, ufst_common_font_data *d, const char *xlatmap, const char *font_kind,
412 int (*choose_proc)(fapi_ufst_server *r, ufst_common_font_data *d, const char *cmapId))
413 { const char *p = xlatmap;
414
415 while(*p) {
416 int good_kind =!strcmp(p, font_kind);
417 p += strlen(p) + 2;
418 while(*p) {
419 const char *cmapId = p, *decodingID = p + strlen(p) + 1;
420 strncpy(d->decodingID, decodingID, sizeof(d->decodingID));
421 if (!decodingID[0])
422 break;
423 p = decodingID + strlen(decodingID) + 1;
424 if (good_kind)
425 if (choose_proc(r, d, cmapId))
426 return;
427 }
428 }
429 d->decodingID[0] = 0;
430 }
431
choose_decoding(fapi_ufst_server * r,ufst_common_font_data * d,const char * xlatmap)432 static void choose_decoding(fapi_ufst_server *r, ufst_common_font_data *d, const char *xlatmap)
433 { if (xlatmap != 0)
434 switch (d->font_type) {
435 case FC_IF_TYPE: /* fixme */ break;
436 case FC_PST1_TYPE: scan_xlatmap(r, d, xlatmap, "PostScript", choose_decoding_general); break;
437 case FC_TT_TYPE: scan_xlatmap(r, d, xlatmap, "TrueType", choose_decoding_TT); break;
438 case FC_FCO_TYPE: scan_xlatmap(r, d, xlatmap, "Microtype", choose_decoding_general); break;
439 }
440 }
441
store_word(byte ** p,ushort w)442 static inline void store_word(byte **p, ushort w)
443 { *((*p)++) = w / 256;
444 *((*p)++) = w % 256;
445
446 }
447
get_TT_glyph(fapi_ufst_server * r,FAPI_font * ff,UW16 chId)448 static LPUB8 get_TT_glyph(fapi_ufst_server *r, FAPI_font *ff, UW16 chId)
449 { pcleo_glyph_list_elem *g;
450 PCLETTO_CHDR *h;
451 ufst_common_font_data *d = (ufst_common_font_data *)r->fc.font_hdr - 1;
452 LPUB8 q;
453 ushort glyph_length = ff->get_glyph(ff, chId, 0, 0);
454 bool use_XL_format = ff->is_mtx_skipped;
455
456 /*
457 * The client must set ff->is_mtx_skipped iff
458 * it requests a replaced lsb for True Type.
459 * If it is set, a replaced width to be supplied.
460 * This constraint is derived from UFST restriction :
461 * the font header format must be compatible with
462 * glyph header format.
463 */
464
465 if (glyph_length == (ushort)-1) {
466 r->callback_error = e_invalidfont;
467 return 0;
468 }
469 g = (pcleo_glyph_list_elem *)gs_malloc(r->mem,
470 sizeof(pcleo_glyph_list_elem) +
471 (use_XL_format ? 12 : sizeof(PCLETTO_CHDR)) + glyph_length + 2, 1,
472 "PCLETTO char");
473 if (g == 0) {
474 r->callback_error = e_VMerror;
475 return 0;
476 }
477 g->chId = chId;
478 g->next = d->glyphs;
479 d->glyphs = g;
480 h = (PCLETTO_CHDR *)(g + 1);
481 h->h.format = 15;
482 if (use_XL_format) {
483 h->h.continuation = 2;
484 q = (LPUB8)h + 2;
485 store_word(&q, (ushort)(glyph_length + 10));
486 store_word(&q, (ushort)(r->sb_x >> r->If.frac_shift)); /* see can_replace_metrics */
487 store_word(&q, (ushort)(r->aw_x >> r->If.frac_shift));
488 store_word(&q, 0);
489 store_word(&q, chId);
490 } else {
491 h->h.continuation = 0;
492 h->h.descriptorsize = 4;
493 h->h.ch_class = 15;
494 h->add_data = 0;
495 q = (LPUB8)&h->charDataSize;
496 store_word(&q, (ushort)(glyph_length + 4));
497 store_word(&q, chId);
498 }
499 if (ff->get_glyph(ff, chId, (LPUB8)q, glyph_length) == (ushort)-1) {
500 r->callback_error = e_invalidfont;
501 return 0;
502 }
503 q += glyph_length;
504 store_word(&q, 0); /* checksum */
505 return (LPUB8)h;
506 /*
507 * The metrics replacement here is done only for the case
508 * corresponding to non-disk TT fonts with MetricsCount != 0;
509 * Other cases are not supported because UFST cannot handle them.
510 * Here we don't take care of cases which can_replace_metrics rejects.
511 *
512 * We don't care of metrics for subglyphs, because
513 * it is ignored by TT interpreter.
514 */
515 }
516
get_T1_glyph(fapi_ufst_server * r,FAPI_font * ff,UW16 chId)517 static LPUB8 get_T1_glyph(fapi_ufst_server *r, FAPI_font *ff, UW16 chId)
518 {
519 #if PST1_SFNTI
520 #if UFST_VERSION_MAJOR >= 6 && UFST_VERSION_MINOR >= 2
521 ushort glyph_length = ff->get_glyph(ff, chId, 0, 0);
522 CDATASTR charstring;
523 PCDATASTR_DEMO pcharstring;
524 byte *cstring;
525 ufst_common_font_data *d = (ufst_common_font_data *)r->fc.font_hdr - 1;
526 MEM_HANDLE hndl;
527 FSA_FROM_SERVER;
528
529 d->glyphs = NULL;
530
531 charstring.len = glyph_length;
532 charstring.hdata = BUFalloc(charstring.len);
533 if (!charstring.hdata)
534 {
535 r->callback_error = e_VMerror;
536 return (NULL);
537 }
538
539 cstring = (unsigned char *)MEMptr(charstring.hdata);
540
541 if (ff->get_glyph(ff, chId, cstring, glyph_length) != glyph_length)
542 {
543 r->callback_error = e_VMerror;
544 BUFfree(charstring.hdata);
545 return (NULL);
546 }
547
548 hndl = BUFalloc (FSA (SL32)(sizeof (CDATASTR)));
549 if (!hndl)
550 {
551 r->callback_error = e_VMerror;
552 BUFfree(charstring.hdata);
553 return (NULL);
554 }
555
556 pcharstring = (PCDATASTR_DEMO)MEMptr(hndl);
557
558 pcharstring->len = charstring.len; /* Datalen */
559 pcharstring->hdata = charstring.hdata;
560 pcharstring->decrypted = 1;
561
562 return ((LPUB8) pcharstring);
563 #else
564 ushort glyph_length = ff->get_glyph(ff, chId, 0, 0);
565 LPUB8 q;
566 pcleo_glyph_list_elem *g = (pcleo_glyph_list_elem *)gs_malloc(r->mem,
567 sizeof(pcleo_glyph_list_elem) + sizeof(PS_CHAR_HDR) + 2 + 2 + glyph_length + 1, 1, "PSEO char");
568 PS_CHAR_HDR *h;
569 ufst_common_font_data *d = (ufst_common_font_data *)r->fc.font_hdr - 1;
570 FSA_FROM_SERVER;
571
572 if (g == 0 || glyph_length == (ushort)-1) {
573 r->callback_error = e_invalidfont;
574 return 0;
575 }
576 g->chId = chId;
577 g->next = d->glyphs;
578 d->glyphs = g;
579 h = (PS_CHAR_HDR *)(g + 1);
580 h->format = 30; /* raster=4, DJ=5, IF=10, TT=15, PS=30 */
581 h->continuation = 0; /* always 0 */
582 h->descriptorsize = 2; /* always 2 */
583 h->ch_class = 11; /* contour=3, compound=4, tt=10, ps=11 */
584 h->len = 0; /* # of bytes to follow (not including csum) */
585 q = (byte *)h + sizeof(*h);
586 /* A workaround for UFST4.6 bug in t1idecod.c (UNPACK_WORD uses pIFS->ph instead ph) :
587 setting Namelen=4, rather normally it must be 0. */
588 q[0] = 0; /* Namelen */
589 q[1] = 4; /* Namelen */
590 q[2] = (glyph_length) / 256; /* Datalen */
591 q[3] = (glyph_length) % 256; /* Datalen */
592 /* Glyph name goes here, but we don't use it. */
593 q += 4;
594 glyph_length = ff->get_glyph(ff, chId, q, glyph_length);
595 q += glyph_length;
596 *q = 1; /* Decrypt flag */
597 pIFS->ph = (byte *)h + sizeof(*h); /* A workaround for UFST4.6 bug in t1idecod.c (UNPACK_WORD uses pIFS->ph instead ph) */
598 return (LPUB8)h;
599 #endif
600 #else
601 return 0;
602 #endif
603 }
604
find_glyph(ufst_common_font_data * d,UW16 chId)605 static pcleo_glyph_list_elem * find_glyph(ufst_common_font_data *d, UW16 chId)
606 { pcleo_glyph_list_elem *e;
607
608 for (e = d->glyphs; e != 0; e = e->next)
609 if (e->chId == chId)
610 return e;
611 return 0;
612 }
613
614 /* UFST callback : */
impl_PCLchId2ptr(FSP UW16 chId)615 static LPUB8 impl_PCLchId2ptr(FSP UW16 chId)
616 {
617 #if UFST_REENTRANT
618 fapi_ufst_server *r = IFS_to_I(pIFS);
619 #else
620 fapi_ufst_server *r = static_server_ptr_for_ufst_callback;
621 #endif
622 FAPI_font *ff = r->ff;
623 ufst_common_font_data *d = (ufst_common_font_data *)r->fc.font_hdr - 1;
624 pcleo_glyph_list_elem *g = find_glyph(d, chId);
625 LPUB8 result = 0;
626
627 if (g != 0)
628 result = (LPUB8)(g + 1);
629 if ((r->fc.format & FC_FONTTYPE_MASK) == FC_PST1_TYPE)
630 result = get_T1_glyph(r, ff, chId);
631 if ((r->fc.format & FC_FONTTYPE_MASK) == FC_TT_TYPE)
632 result = get_TT_glyph(r, ff, chId);
633 return result;
634 }
635
pack_word(LPUB8 * p,UW16 v)636 static inline void pack_word(LPUB8 *p, UW16 v)
637 { LPUB8 q = (LPUB8)&v;
638
639 #if (BYTEORDER == LOHI) /* defied in UFST includes */
640 (*p)[1] = q[0];
641 (*p)[0] = q[1];
642 #else
643 *(UW16 *)(*p) = v;
644 #endif
645 *p += 2;
646 }
647
pack_long(LPUB8 * p,UL32 v)648 static inline void pack_long(LPUB8 *p, UL32 v)
649 { LPUB8 q = (LPUB8)&v;
650
651 #if (BYTEORDER == LOHI) /* defied in UFST includes */
652 (*p)[3] = q[0];
653 (*p)[2] = q[1];
654 (*p)[1] = q[2];
655 (*p)[0] = q[3];
656 #else
657 *(UL32 *)(*p) = v;
658 #endif
659 *p += 4;
660 }
661
pack_float(LPUB8 * p,float v)662 static inline void pack_float(LPUB8 *p, float v)
663 { sprintf((char *)(*p), "%f", v);
664 *p += strlen((const char *)*p) + 1;
665 }
666
667 #define PACK_ZERO(p) *(p++) = 0
668 #define PACK_BYTE(p, c) *(p++) = c
669 #define PACK_WORD(p, i, var) pack_word(&p, ff->get_word(ff, var, i))
670 #define PACK_LONG(p, i, var) pack_long(&p, ff->get_long(ff, var, i))
671
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)672 static void pack_pseo_word_array(fapi_ufst_server *r, FAPI_font *ff, UB8 **p,
673 UW16 max_count, fapi_font_feature count_id, fapi_font_feature array_id)
674 { UW16 k = min(ff->get_word(ff, count_id, 0), max_count), j;
675
676 pack_word(p, k);
677 for (j = 0; j < k; j++)
678 PACK_WORD(*p, j, array_id);
679 for (; j < max_count; j++)
680 pack_word(p, 0);
681 }
682
pack_pseo_fhdr(fapi_ufst_server * r,FAPI_font * ff,UB8 * p)683 static void pack_pseo_fhdr(fapi_ufst_server *r, FAPI_font *ff, UB8 *p)
684 { ushort j, n, skip = 0;
685
686 while (((uint64_t)p) & 0x03) /* align to QUADWORD */
687 PACK_ZERO(p);
688 pack_long(&p, 1); /* format = 1 */
689 for (j = 0; j < 6; j++)
690 pack_float(&p, ff->get_float(ff, FAPI_FONT_FEATURE_FontMatrix, j));
691 while (((uint64_t)p) & 0x03) /* align to QUADWORD */
692 PACK_ZERO(p);
693 /* UFST has no definition for PSEO structure, so implement serialization : */
694 PACK_LONG(p, 0, FAPI_FONT_FEATURE_UniqueID);
695 PACK_LONG(p, 0, FAPI_FONT_FEATURE_BlueScale);
696 PACK_WORD(p, 0, FAPI_FONT_FEATURE_Weight);
697 PACK_WORD(p, 0, FAPI_FONT_FEATURE_ItalicAngle);
698 PACK_WORD(p, 0, FAPI_FONT_FEATURE_IsFixedPitch);
699 PACK_WORD(p, 0, FAPI_FONT_FEATURE_UnderLinePosition);
700 PACK_WORD(p, 0, FAPI_FONT_FEATURE_UnderlineThickness);
701 PACK_WORD(p, 0, FAPI_FONT_FEATURE_FontType);
702 PACK_WORD(p, 0, FAPI_FONT_FEATURE_FontBBox);
703 PACK_WORD(p, 1, FAPI_FONT_FEATURE_FontBBox);
704 PACK_WORD(p, 2, FAPI_FONT_FEATURE_FontBBox);
705 PACK_WORD(p, 3, FAPI_FONT_FEATURE_FontBBox);
706 pack_pseo_word_array(r, ff, &p, 14, FAPI_FONT_FEATURE_BlueValues_count, FAPI_FONT_FEATURE_BlueValues);
707 pack_pseo_word_array(r, ff, &p, 10, FAPI_FONT_FEATURE_OtherBlues_count, FAPI_FONT_FEATURE_OtherBlues);
708 pack_pseo_word_array(r, ff, &p, 14, FAPI_FONT_FEATURE_FamilyBlues_count, FAPI_FONT_FEATURE_FamilyBlues);
709 pack_pseo_word_array(r, ff, &p, 10, FAPI_FONT_FEATURE_FamilyOtherBlues_count, FAPI_FONT_FEATURE_FamilyOtherBlues);
710 PACK_WORD(p, 0, FAPI_FONT_FEATURE_BlueShift);
711 PACK_WORD(p, 0, FAPI_FONT_FEATURE_BlueFuzz);
712 PACK_WORD(p, 0, FAPI_FONT_FEATURE_StdHW);
713 PACK_WORD(p, 0, FAPI_FONT_FEATURE_StdVW);
714 pack_pseo_word_array(r, ff, &p, 12, FAPI_FONT_FEATURE_StemSnapH_count, FAPI_FONT_FEATURE_StemSnapH);
715 pack_pseo_word_array(r, ff, &p, 12, FAPI_FONT_FEATURE_StemSnapV_count, FAPI_FONT_FEATURE_StemSnapV);
716 PACK_WORD(p, 0, FAPI_FONT_FEATURE_ForceBold);
717 PACK_WORD(p, 0, FAPI_FONT_FEATURE_LanguageGroup);
718 PACK_WORD(p, 0, FAPI_FONT_FEATURE_lenIV);
719 for (j = 0; j < 12; j++)
720 PACK_ZERO(p), PACK_ZERO(p); /* Reserved2 */
721 /* max data size = 107 words + 6 floats in ASCII */
722 n = ff->get_word(ff, FAPI_FONT_FEATURE_Subrs_count, 0);
723 pack_word(&p, n);
724 for (j = 0; j < n; j++) {
725 ushort subr_len = ff->get_subr(ff, j, 0, 0);
726 if (subr_len != 0) {
727 pack_word(&p, j);
728 pack_word(&p, subr_len);
729 PACK_BYTE(p, 1); /* is_decrypted */
730 ff->get_subr(ff, j, p, subr_len);
731 p += subr_len;
732 } else
733 skip = 1;
734 }
735 n = ff->get_word(ff, FAPI_FONT_FEATURE_GlobalSubrs_count, 0);
736 /* get_word() doesn't have an error return value, so I've used an unlikely value */
737 if (n != 65535) {
738 pack_word(&p, n);
739 for (j = 0; j < n; j++) {
740 ushort subr_len = ff->get_gsubr(ff, j, 0, 0);
741 if (subr_len != 0) {
742 pack_word(&p, j);
743 pack_word(&p, subr_len);
744 PACK_BYTE(p, 1); /* is_decrypted */
745 ff->get_gsubr(ff, j, p, subr_len);
746 p += subr_len;
747 } else
748 skip = 1;
749 }
750 }
751 if (skip)
752 pack_word(&p, 0xFFFF);
753 }
754
my_strdup(fapi_ufst_server * r,const char * s,const char * cname)755 static char *my_strdup(fapi_ufst_server *r, const char *s, const char *cname)
756 { int len = strlen(s) + 1;
757 char *p = (char *)gs_malloc(r->mem, len, 1, cname);
758
759 if (p != 0)
760 memcpy(p, s, len);
761 return p;
762 }
763
fco_open(fapi_ufst_server * r,const char * font_file_path,fco_list_elem ** result)764 static FAPI_retcode fco_open(fapi_ufst_server *r, const char *font_file_path, fco_list_elem **result)
765 { int code;
766 fco_list_elem *e = gx_UFST_find_static_fco(font_file_path);
767
768 if (e != NULL) {
769 *result = e;
770 return 0;
771 }
772 for (e = r->fco_list; e != 0; e = e->next) {
773 if (!strcmp(e->file_path, font_file_path))
774 break;
775 }
776 if (e == 0) {
777 SW16 fcHandle;
778 FSA_FROM_SERVER;
779
780 if ((code = CGIFfco_Open(FSA (UB8 *)font_file_path, &fcHandle)) != 0)
781 return code;
782 e = (fco_list_elem *)gs_malloc(r->mem, sizeof(*e), 1, "fco_list_elem");
783 if (e == 0) {
784 CGIFfco_Close(FSA fcHandle);
785 return e_VMerror;
786 }
787 e->open_count = 0;
788 e->fcHandle = fcHandle;
789 e->file_path = my_strdup(r, font_file_path, "fco_file_path");
790 if (e->file_path == 0) {
791 CGIFfco_Close(FSA fcHandle);
792 gs_free(r->mem, e, 0, 0, "fco_list_elem");
793 return e_VMerror;
794 }
795 e->next = r->fco_list;
796 r->fco_list = e;
797 }
798 e->open_count++;
799 *result = e;
800 return 0;
801 }
802
make_font_data(fapi_ufst_server * r,const char * font_file_path,FAPI_font * ff,ufst_common_font_data ** return_data)803 static FAPI_retcode make_font_data(fapi_ufst_server *r, const char *font_file_path, FAPI_font *ff, ufst_common_font_data **return_data)
804 { ulong area_length = sizeof(ufst_common_font_data), tt_size = 0;
805 LPUB8 buf;
806 PCLETTO_FHDR *h;
807 ufst_common_font_data *d;
808 bool use_XL_format = ff->is_mtx_skipped;
809 int code;
810 FSA_FROM_SERVER;
811
812 *return_data = 0;
813 r->fc.ttc_index = ff->subfont;
814 if (ff->font_file_path == NULL) {
815 #if UFST_VERSION_MAJOR < 6
816 return(e_invalidaccess);
817 #else
818 area_length += PCLETTOFONTHDRSIZE;
819 if (ff->is_type1) {
820 int subrs_count = ff->get_word(ff, FAPI_FONT_FEATURE_Subrs_count, 0);
821 int subrs_length = ff->get_long(ff, FAPI_FONT_FEATURE_Subrs_total_size, 0);
822 int subrs_area_size;
823 int gsubrs_count = ff->get_word(ff, FAPI_FONT_FEATURE_GlobalSubrs_count, 0);
824
825 /* get_word() doesn't have an error return value, so I've used an unlikely value */
826 if (gsubrs_count != 65535)
827 subrs_count += gsubrs_count;
828
829 subrs_area_size = subrs_count * 5 + subrs_length + 2;
830 area_length += 360 + subrs_area_size; /* some inprecise - see pack_pseo_fhdr */
831 } else {
832 tt_size = ff->get_long(ff, FAPI_FONT_FEATURE_TT_size, 0);
833 if (tt_size == 0)
834 return e_invalidfont;
835 area_length += tt_size + (use_XL_format ? 6 : 4) + 4 + 2;
836 }
837 #endif
838 } else {
839 #if UFST_VERSION_MAJOR < 6
840 int sind = strlen(font_file_path) - 1;
841
842 if ((font_file_path[sind] != 'o' || font_file_path[sind] != 'O') &&
843 (font_file_path[sind - 1] != 'c' || font_file_path[sind - 1] != 'C') &&
844 (font_file_path[sind - 2] != 'f' || font_file_path[sind - 2] != 'F') &&
845 font_file_path[sind - 3] != '.') {
846 return(e_invalidaccess);
847 }
848 #endif
849 area_length += strlen(font_file_path) + 1;
850 }
851 buf = gs_malloc(r->mem, area_length, 1, "ufst font data");
852 if (buf == 0)
853 return e_VMerror;
854
855 memset(buf, 0x00, area_length);
856
857 d = (ufst_common_font_data *)buf;
858 d->tt_font_body_offset = 0;
859 d->platformId = 0;
860 d->specificId = 0;
861 d->decodingID[0] = 0;
862 d->glyphs = 0;
863 d->is_disk_font = (ff->font_file_path != NULL);
864 if (d->is_disk_font) {
865 fco_list_elem *e = gx_UFST_find_static_fco(font_file_path);
866
867 if (e != NULL) {
868 memcpy(d + 1, font_file_path, strlen(font_file_path) + 1);
869 d->font_id = (e->fcHandle << 16) | ff->subfont;
870 d->font_type = FC_FCO_TYPE;
871 } else {
872 stream *f = sfopen(font_file_path, "rb", r->mem);
873 if (f == NULL) {
874 emprintf1(r->mem,
875 "fapiufst: Can't open %s\n",
876 font_file_path);
877 return e_undefinedfilename;
878 }
879 memcpy(d + 1, font_file_path, strlen(font_file_path) + 1);
880 d->font_type = get_font_type(f);
881 sfclose(f);
882 if (d->font_type == FC_FCO_TYPE) {
883 fco_list_elem *e;
884 if ((code = fco_open(r, font_file_path, &e)) != 0)
885 return code;
886 d->font_id = (e->fcHandle << 16) | ff->subfont;
887 }
888 }
889 } else {
890 d->font_type = (ff->is_type1 ? FC_PST1_TYPE : FC_TT_TYPE);
891 d->font_id = ff->get_long(ff, FAPI_FONT_FEATURE_UniqueID, 0);
892 if (d->font_id < 0) {
893 d->font_id = assign_font_id();
894 }
895 h = (PCLETTO_FHDR *)(buf + sizeof(ufst_common_font_data));
896 h->fontDescriptorSize = PCLETTOFONTHDRSIZE;
897 h->descriptorFormat = 15;
898 h->fontType = 11; /* wrong */ /* 3- 11=Unicode; 0,1,2 also possible */
899 h->style_msb = 0; /* wrong */ /* 4- from PCLT table in TrueType font */
900 h->reserved1 = 0;
901 h->baselinePosition = 0; /* wrong */ /* 6- from head table in TT font; = 0 */
902 h->cellWidth = 1024; /* wrong */ /* 8- head, use xMax - xMin */
903 h->cellHeight = 1024; /* wrong */ /* 10- head, use yMax - yMin */
904 h->orientation = 0; /* 12- 0 */
905 h->spacing = 1; /* wrong */ /* 13- 1=proportional, 0-fixed pitch */
906 h->characterSet = 56; /* wrong */ /* 14- same as symSetCode; =56 if unbound. */
907 h->pitch = 1024; /* wrong */ /* 16- PCLT */
908 h->height = 0; /* 18- 0 if TrueType */
909 h->xHeight = 512; /* wrong */ /* 20- PCLT */
910 h->widthType = 0; /* wrong */ /* 22- PCLT */
911 h->style_lsb = 0; /* wrong */ /* 23- PCLT */
912 h->strokeWeight = 0; /* wrong */ /* 24- PCLT */
913 h->typeface_lsb = 0; /* wrong */ /* 25- PCLT */
914 h->typeface_msb = 0; /* wrong */ /* 26- PCLT */
915 h->serifStyle = 0; /* wrong */ /* 27- PCLT */
916 h->quality = 0; /* wrong */ /* 28- 2 if TrueType */
917 h->placement = 0; /* wronfg */ /* 29- 0 if TrueType */
918 h->underlinePosition = 0; /* 30- 0 */
919 h->underlineHeight = 0; /* 31- 0 */
920 h->textHeight = 102; /* wrong */ /* 32- from OS/2 table in TT font */
921 h->textWidth = 1024; /* wrong */ /* 34- OS/2 */
922 h->firstCode = 0; /* 36- set to 0 if unbound */
923 h->lastCode = 255; /* wrong */ /* 38- max number of downloadable chars if unbound */
924 h->pitch_ext = 0; /* 40- 0 if TrueType */
925 h->height_ext = 0; /* 41- 0 if TrueType */
926 h->capHeight = 1024; /* wrong */ /* 42- PCLT */
927 h->fontNumber = d->font_id; /* 44- PCLT */
928 h->fontName[0] = 0; /* wrong */ /* 48- PCLT */
929 h->scaleFactor = 1024; /* wrong */ /* 64- head:unitsPerEm */
930 h->masterUnderlinePosition = 0; /* wrong */ /* 66- post table, or -20% of em */
931 h->masterUnderlineHeight = 0; /* wrong */ /* 68- post table, or 5% of em */
932 h->fontScalingTechnology = 1; /* 70- 1=TrueType; 0=Intellifont */
933 h->variety = 0; /* 71- 0 if TrueType */
934 memset((LPUB8)h + PCLETTOFONTHDRSIZE, 0 ,8); /* work around bug in PCLswapHdr : it wants format 10 */
935 /* fixme : Most fields above being marked "wrong" look unused by UFST.
936 Need to check for sure.
937 */
938 /* fixme : This code assumes 1-byte alignment for PCLETTO_FHDR structure.
939 Use PACK_* macros to improve.
940 */
941 PCLswapHdr(FSA (UB8 *)h, 0);
942 if (ff->is_type1) {
943 LPUB8 fontdata = (LPUB8)h + PCLETTOFONTHDRSIZE;
944 pack_pseo_fhdr(r, ff, fontdata);
945 } else {
946 LPUB8 pseg = (LPUB8)h + PCLETTOFONTHDRSIZE;
947 LPUB8 fontdata = pseg + (use_XL_format ? 6 : 4);
948 if (tt_size > 65000)
949 return e_unregistered; /* Must not happen because we skept 'glyp', 'loca' and 'cmap'. */
950 pseg[0] = 'G';
951 pseg[1] = 'T';
952 if (use_XL_format) {
953 pseg[2] = tt_size >> 24;
954 pseg[3] = (tt_size >> 16) % 256;
955 pseg[4] = (tt_size >> 8) % 256;
956 pseg[5] = tt_size % 256;
957 } else {
958 pseg[2] = tt_size / 256;
959 pseg[3] = tt_size % 256;
960 }
961 d->tt_font_body_offset = (LPUB8)fontdata - (LPUB8)d;
962 if (ff->serialize_tt_font(ff, fontdata, tt_size))
963 return e_invalidfont;
964 *(fontdata + tt_size ) = 255;
965 *(fontdata + tt_size + 1) = 255;
966 *(fontdata + tt_size + 2) = 0;
967 *(fontdata + tt_size + 3) = 0;
968 *(fontdata + tt_size + 4) = 0;
969 *(fontdata + tt_size + 5) = 0; /* checksum */
970 }
971 }
972 *return_data = d;
973 return 0;
974 }
975
prepare_typeface(fapi_ufst_server * r,ufst_common_font_data * d)976 static void prepare_typeface(fapi_ufst_server *r, ufst_common_font_data *d)
977 { r->fc.format = d->font_type;
978 r->fc.font_id = d->font_id;
979 r->fc.font_hdr = (UB8 *)(d + 1);
980 if (!d->is_disk_font)
981 r->fc.format |= FC_EXTERN_TYPE;
982 }
983
get_scaled_font(FAPI_server * server,FAPI_font * ff,const FAPI_font_scale * font_scale,const char * xlatmap,FAPI_descendant_code dc)984 static FAPI_retcode get_scaled_font(FAPI_server *server, FAPI_font *ff,
985 const FAPI_font_scale *font_scale, const char *xlatmap, FAPI_descendant_code dc)
986 { fapi_ufst_server *r = If_to_I(server);
987 FONTCONTEXT *fc = &r->fc;
988 /* Note : UFST doesn't provide handles for opened fonts,
989 but copies FONTCONTEXT to IFSTATE and caches it.
990 Due to this the plugin cannot provide a handle for the font.
991 This assumes that only one font context is active at a moment.
992 */
993 ufst_common_font_data *d = (ufst_common_font_data *)ff->server_font_data;
994 const double scale = F_ONE;
995 double hx, hy;
996 FAPI_retcode code = 0;
997 bool use_XL_format = ff->is_mtx_skipped;
998 int world_scale = 0;
999 FONT_METRICS fm;
1000 FSA_FROM_SERVER;
1001
1002 if (ff->is_cid && ff->is_type1 && ff->font_file_path == NULL &&
1003 (dc == FAPI_TOPLEVEL_BEGIN || dc == FAPI_TOPLEVEL_COMPLETE)) {
1004 /* Don't need any processing for the top level font of a non-disk CIDFontType 0.
1005 See comment in FAPI_prepare_font.
1006 Will do with its subfonts individually.
1007 */
1008 return 0;
1009 }
1010
1011 ff->need_decrypt = 1;
1012 if (d == 0) {
1013 if ((code = make_font_data(r, ff->font_file_path, ff, &d)) != 0)
1014 return code;
1015 ff->server_font_data = d;
1016 prepare_typeface(r, d);
1017 if (ff->font_file_path != NULL || ff->is_type1) /* such fonts don't use RAW_GLYPH */
1018 choose_decoding(r, d, xlatmap);
1019 }
1020 else {
1021 prepare_typeface(r, d);
1022 if (ff->font_file_path != NULL || ff->is_type1) /* such fonts don't use RAW_GLYPH */
1023 choose_decoding(r, d, xlatmap);
1024 }
1025
1026 r->tran_xx = font_scale->matrix[0] / scale, r->tran_xy = font_scale->matrix[1] / scale;
1027 r->tran_yx = font_scale->matrix[2] / scale, r->tran_yy = font_scale->matrix[3] / scale;
1028 hx = hypot(r->tran_xx, r->tran_xy), hy = hypot(r->tran_yx, r->tran_yy);
1029 fc->xspot = F_ONE;
1030 fc->yspot = F_ONE;
1031 fc->fc_type = FC_MAT2_TYPE;
1032
1033 fc->s.m2.m[0] = (int)((double)font_scale->matrix[0] / hx + 0.5);
1034 fc->s.m2.m[1] = (int)((double)font_scale->matrix[1] / hx + 0.5);
1035 fc->s.m2.m[2] = (int)((double)font_scale->matrix[2] / hy + 0.5);
1036 fc->s.m2.m[3] = (int)((double)font_scale->matrix[3] / hy + 0.5);
1037 fc->s.m2.matrix_scale = 16;
1038 fc->s.m2.xworld_res = font_scale->HWResolution[0] >> 16;
1039 fc->s.m2.yworld_res = font_scale->HWResolution[1] >> 16;
1040
1041 if ((hx > 0 && hy > 0) && (hx < 1.5 || hy < 1.5)) {
1042 world_scale = 8;
1043 hx *= 256;
1044 hy *= 256;
1045
1046 while (hx < 1.5 || hy < 1.5) {
1047 world_scale += 8;
1048 hx *= 256;
1049 hy *= 256;
1050 }
1051 }
1052 fc->s.m2.world_scale = world_scale;
1053 fc->s.m2.point_size = (int)(hy * 8 + 0.5); /* 1/8ths of pixels */
1054 fc->s.m2.set_size = (int)(hx * 8 + 0.5);
1055 fc->numXsubpixels = font_scale->subpixels[0];
1056 fc->numYsubpixels = font_scale->subpixels[1];
1057 fc->alignment = (font_scale->align_to_pixels ? GAGG : GAPP);
1058 fc->ExtndFlags = 0;
1059 if (d->font_type == FC_TT_TYPE)
1060 fc->ssnum = USER_CMAP;
1061 else if (d->font_type == FC_FCO_TYPE) {
1062 fc->ssnum = UNICODE;
1063 } else if (d->font_type == FC_PST1_TYPE) {
1064 fc->ssnum = T1ENCODING;
1065 }
1066
1067 if (d->font_type != FC_TT_TYPE && d->font_type != FC_FCO_TYPE) {
1068 fc->ExtndFlags = EF_NOSYMSETMAP;
1069 }
1070 fc->ExtndFlags |= EF_SUBSTHOLLOWBOX_TYPE;
1071 fc->format |= FC_NON_Z_WIND; /* NON_ZERO Winding required for TrueType */
1072 fc->format |= FC_INCHES_TYPE; /* output in units per inch */
1073 fc->user_platID = d->platformId;
1074 fc->user_specID = d->specificId;
1075 if (use_XL_format)
1076 fc->ExtndFlags |= EF_XLFONT_TYPE;
1077 if (ff->is_vertical)
1078 fc->ExtndFlags |= EF_UFSTVERT_TYPE;
1079 fc->dl_ssnum = (d->specificId << 4) | d->platformId;
1080 fc->ttc_index = ff->subfont;
1081 r->callback_error = 0;
1082
1083 code = CGIFfont(FSA fc);
1084 if (r->callback_error != 0)
1085 return r->callback_error;
1086
1087 code = CGIFfont_metrics(&fm);
1088 if (r->callback_error != 0)
1089 return r->callback_error;
1090
1091 return code;
1092 }
1093
get_decodingID(FAPI_server * server,FAPI_font * ff,const char ** decodingID_result)1094 static FAPI_retcode get_decodingID(FAPI_server *server, FAPI_font *ff, const char **decodingID_result)
1095 { fapi_ufst_server *r = If_to_I(server);
1096 ufst_common_font_data *d = (ufst_common_font_data *)r->fc.font_hdr - 1;
1097
1098 *decodingID_result = d->decodingID;
1099 return 0;
1100 }
1101
get_font_bbox(FAPI_server * server,FAPI_font * ff,int BBox[4])1102 static FAPI_retcode get_font_bbox(FAPI_server *server, FAPI_font *ff, int BBox[4])
1103 { fapi_ufst_server *r = If_to_I(server);
1104 SW16 VLCPower = 0;
1105 int code;
1106 FSA_FROM_SERVER;
1107
1108 if ((code = CGIFbound_box(FSA BBox, &VLCPower)) < 0)
1109 return code;
1110 /* UFST expands bbox for internal needs, and retrives the expanded bbox.
1111 We believe it's bug in UFST.
1112 Now we collapse it back to the correct size :
1113 */
1114 BBox[0] += 2;
1115 BBox[1] += 2;
1116 BBox[2] -= 2;
1117 BBox[3] -= 2;
1118 BBox[0] >>= VLCPower;
1119 BBox[1] >>= VLCPower;
1120 BBox[2] >>= VLCPower;
1121 BBox[3] >>= VLCPower;
1122 return 0;
1123 }
1124
get_font_proportional_feature(FAPI_server * server,FAPI_font * ff,bool * bProportional)1125 static FAPI_retcode get_font_proportional_feature(FAPI_server *server, FAPI_font *ff, bool *bProportional)
1126 { fapi_ufst_server *r = If_to_I(server);
1127 FSA_FROM_SERVER;
1128
1129 *bProportional = FALSE;
1130 if (ff->font_file_path == NULL || ff->is_type1)
1131 return 0;
1132 #if TT_ROM || TT_DISK
1133 {
1134 UB8 buf[74];
1135 UL32 length = sizeof(buf);
1136
1137 if (CGIFtt_query(FSA (UB8 *)ff->font_file_path, *(UL32 *)"OS/2", (UW16)ff->subfont, &length, buf) != 0)
1138 return 0; /* No OS/2 table - no chance to get the info. Use default == FALSE. */
1139 *bProportional = (buf[35] == 9);
1140 }
1141 #endif
1142 return 0;
1143 }
1144
make_asciiz_char_name(char * buf,int buf_length,FAPI_char_ref * c)1145 static inline void make_asciiz_char_name(char *buf, int buf_length, FAPI_char_ref *c)
1146 { int len = min(buf_length - 1, c->char_name_length);
1147
1148 memcpy(buf, c->char_name, len);
1149 buf[len] = 0;
1150 }
1151
1152 #define MAX_CHAR_NAME_LENGTH 30
1153
can_retrieve_char_by_name(FAPI_server * server,FAPI_font * ff,FAPI_char_ref * c,int * result)1154 static FAPI_retcode can_retrieve_char_by_name(FAPI_server *server, FAPI_font *ff, FAPI_char_ref *c, int *result)
1155 { fapi_ufst_server *r = If_to_I(server);
1156 FSA_FROM_SERVER;
1157
1158 *result = 0;
1159
1160 switch (r->fc.format & FC_FONTTYPE_MASK) {
1161 case FC_PST1_TYPE :
1162 *result = 1;
1163 break;
1164 case FC_TT_TYPE :
1165 break;
1166 }
1167
1168 return 0;
1169 }
1170
can_replace_metrics(FAPI_server * server,FAPI_font * ff,FAPI_char_ref * c,int * result)1171 static FAPI_retcode can_replace_metrics(FAPI_server *server, FAPI_font *ff, FAPI_char_ref *c, int *result)
1172 { *result = (!ff->is_type1 && ff->font_file_path == NULL &&
1173 c->metrics_scale == 0 && c->metrics_type == FAPI_METRICS_REPLACE);
1174 return 0;
1175 }
1176
release_glyphs(fapi_ufst_server * r,ufst_common_font_data * d)1177 static void release_glyphs(fapi_ufst_server *r, ufst_common_font_data *d)
1178 {
1179 if (d) {
1180 while (d->glyphs != 0) {
1181 pcleo_glyph_list_elem *e = d->glyphs;
1182 d->glyphs = e->next;
1183 gs_free(r->mem, e, 0, 0, "PCLEO char");
1184 }
1185 d->glyphs = NULL;
1186 }
1187 }
1188
get_fontmatrix(FAPI_server * I,gs_matrix * m)1189 static FAPI_retcode get_fontmatrix(FAPI_server *I, gs_matrix *m)
1190 {
1191 fapi_ufst_server *r = If_to_I(I);
1192 ufst_common_font_data *d = (ufst_common_font_data *)I->ff.server_font_data;
1193 FAPI_retcode code = 0;
1194
1195 if (d == 0) {
1196 if ((code = make_font_data(r, I->ff.font_file_path, &(I->ff), &d)) != 0)
1197 return (code);
1198 I->ff.server_font_data = d;
1199 prepare_typeface(r, d);
1200 }
1201
1202 /* There are PS jobs that rely on the standard fonts having
1203 * a FontMatrix of [0.001 0 0 0.001 0 0], but MT fonts actually
1204 * have an identity matrix. We need to compensate here. Other
1205 * fonts need an identity matrix returned here, as we apply the
1206 * font matrix explicitly in the scale calculation in zfapi.c
1207 */
1208 if (d->font_type & FC_FCO_TYPE) {
1209 m->xx = 0.001;
1210 m->xy = 0.0;
1211 m->yx = 0.0;
1212 m->yy = 0.001;
1213 m->tx = 0.0;
1214 m->ty = 0.0;
1215 }
1216 else {
1217 m->xx = 1.0;
1218 m->xy = 0.0;
1219 m->yx = 0.0;
1220 m->yy = 1.0;
1221 m->tx = 0.0;
1222 m->ty = 0.0;
1223 }
1224
1225 #if 0
1226 gs_matrix *base_font_matrix = &I->initial_FontMatrix;
1227 m->xx = I->initial_FontMatrix.xx;
1228 m->xy = I->initial_FontMatrix.xy;
1229 m->yx = I->initial_FontMatrix.yx;
1230 m->yy = I->initial_FontMatrix.yy;
1231 m->tx = I->initial_FontMatrix.tx;
1232 m->ty = I->initial_FontMatrix.ty;
1233 #endif
1234 return (code);
1235
1236 }
1237
export_outline(fapi_ufst_server * r,PIFOUTLINE pol,FAPI_path * p)1238 static int export_outline(fapi_ufst_server *r, PIFOUTLINE pol, FAPI_path *p)
1239 { POUTLINE_CHAR outchar;
1240 SW16 num_contrs,num_segmts;
1241 LPSB8 segment;
1242 PINTRVECTOR points;
1243 SW16 i,j;
1244
1245 if (pol == NULL)
1246 return 0;
1247 p->shift += r->If.frac_shift + pol->VLCpower;
1248 outchar = &pol->ol;
1249 num_contrs = outchar->num_loops;
1250 for(i = 0; i<num_contrs; i++) {
1251 num_segmts = outchar->loop[i].num_segmts;
1252 segment = (LPSB8)((LPSB8)(outchar->loop) + outchar->loop[i].segmt_offset);
1253 points = (PINTRVECTOR)((LPSB8)(outchar->loop) + outchar->loop[i].coord_offset);
1254 for(j=0; j<num_segmts; j++) {
1255
1256 if(*segment == 0x00) {
1257 if ((p->gs_error = p->moveto(p, ((int64_t)points->x) << 16, ((int64_t)points->y) << 16)) != 0)
1258 return p->gs_error;
1259 points++;
1260 } else if (*segment == 0x01) {
1261 if ((p->gs_error = p->lineto(p, ((int64_t)points->x) << 16, ((int64_t)points->y) << 16)) != 0)
1262 return p->gs_error;
1263 points++;
1264 } else if (*segment == 0x02) {
1265 points+=2;
1266 return e_invalidfont; /* This must not happen */
1267 } else if (*segment == 0x03) {
1268 if ((p->gs_error = p->curveto(p, ((int64_t)points[0].x) << 16, ((int64_t)points[0].y) << 16,
1269 ((int64_t)points[1].x) << 16, ((int64_t)points[1].y) << 16,
1270 ((int64_t)points[2].x) << 16, ((int64_t)points[2].y)<< 16) < 0))
1271 return p->gs_error;
1272 points+=3;
1273 } else
1274 return e_invalidfont; /* This must not happen */
1275 segment++;
1276 }
1277 }
1278 return 0;
1279 }
1280
set_metrics(fapi_ufst_server * r,FAPI_metrics * metrics,SL32 design_bbox[4],SW16 design_escapement[2],SW16 du_emx,SW16 du_emy)1281 static inline void set_metrics(fapi_ufst_server *r, FAPI_metrics *metrics, SL32 design_bbox[4], SW16 design_escapement[2], SW16 du_emx, SW16 du_emy)
1282 {
1283
1284 metrics->escapement = design_escapement[0];
1285 metrics->v_escapement = design_escapement[1];
1286 metrics->em_x = du_emx;
1287 metrics->em_y = du_emy;
1288 metrics->bbox_x0 = design_bbox[0];
1289 metrics->bbox_y0 = design_bbox[1];
1290 metrics->bbox_x1 = design_bbox[2];
1291 metrics->bbox_y1 = design_bbox[3];
1292 }
1293
get_char(fapi_ufst_server * r,FAPI_font * ff,FAPI_char_ref * c,FAPI_path * p,FAPI_metrics * metrics,UW16 format)1294 static FAPI_retcode get_char(fapi_ufst_server *r, FAPI_font *ff, FAPI_char_ref *c, FAPI_path *p, FAPI_metrics *metrics, UW16 format)
1295 {
1296 UW16 code = 0, code2 = 0;
1297 UW16 cc = (UW16)c->char_code;
1298 SL32 design_bbox[4];
1299 char PSchar_name[MAX_CHAR_NAME_LENGTH];
1300 MEM_HANDLE result;
1301 ufst_common_font_data *d = (ufst_common_font_data *)ff->server_font_data;
1302 SW16 design_escapement[2];
1303 SW16 du_emx, du_emy;
1304 const char *notdef = ".notdef";
1305 const void *client_char_data = ff->char_data;
1306 const int client_char_data_len = ff->char_data_len;
1307 bool need_decrypt = ff->need_decrypt;
1308 int length;
1309 FSA_FROM_SERVER;
1310
1311 design_escapement[0] = design_escapement[1] = 0;
1312
1313 if (ff->is_type1) {
1314 /* If a charstring in a Type 1 has been replaced with a PS procedure
1315 * get_glyph will return -1. We can then return char_code + 1 which
1316 * tells the FAPI code we might be dealing with a procedure, and to
1317 * try executing it as such.
1318 */
1319 ff->need_decrypt = false;
1320 length = ff->get_glyph(ff, c->char_code, NULL, 0);
1321 ff->need_decrypt = need_decrypt;
1322 if (length == -1) {
1323 return(c->char_code + 1);
1324 }
1325 }
1326
1327 memset(metrics, 0, sizeof(*metrics));
1328 metrics->bbox_x1 = -1;
1329
1330 if (ff->is_type1 && !ff->is_cid) {
1331 int len = min(ff->char_data_len, sizeof(PSchar_name) - 1);
1332 memcpy (PSchar_name, ff->char_data, len);
1333 PSchar_name[len] = 0;
1334 } else {
1335 make_asciiz_char_name(PSchar_name, sizeof(PSchar_name), c);
1336 }
1337
1338 CGIFchIdptr(FSA &cc, PSchar_name); /* fixme : Likely only FC_PST1_TYPE needs it. */
1339 { /* hack : Changing UFST internal data. Change to r->fc doesn't help,
1340 because UFST thinks that the "outline/raster" is a property of current font. */
1341 pIFS->fcCur.format &= ~FC_OUTPUT_MASK;
1342 pIFS->fcCur.format |= format;
1343 }
1344 r->bRaster = FALSE;
1345 r->ff = ff;
1346 r->callback_error = 0;
1347 r->sb_x = c->sb_x;
1348 r->aw_x = c->aw_x;
1349 r->metrics_type = c->metrics_type;
1350 if (d->font_type == FC_FCO_TYPE && r->fc.ExtndFlags & EF_SUBSTHOLLOWBOX_TYPE) {
1351 if (c->char_name != NULL && c->char_name_length == 7 &&
1352 !memcmp(c->char_name, ".notdef", 7)) {
1353 /* With EF_SUBSTHOLLOWBOX_TYPE and FCO,
1354 UFST paints a hollow box insted .notdef .
1355 For Adobe compatibility we substitute a space,
1356 because Adobe Type 1 fonts define .notdef as a space . */
1357 cc = 32;
1358 }
1359 }
1360 #if !UFST_REENTRANT
1361 static_server_ptr_for_ufst_callback = r;
1362 #endif
1363 code = CGIFchar_handle(FSA cc, &result, (SW16)0);
1364 if (code && code != ERR_fixed_space && code != ERR_bm_buff && code != ERR_bm_too_big) {
1365 /* There is no such char in the font, try the glyph 0 (notdef) : */
1366 UW16 c1 = 0, ssnum = pIFS->fcCur.ssnum;
1367
1368 if (d->font_type == FC_FCO_TYPE) {
1369 /* EF_SUBSTHOLLOWBOX_TYPE must work against it.
1370 Ensure the plugin plug__xi.fco is loaded. */
1371 /* fixme : Due to unknown reason EF_SUBSTHOLLOWBOX_TYPE
1372 doesn't work for Symbol, Dingbats, Wingdings.
1373 hack : render the space character. */
1374 c1 = 32;
1375 } else {
1376 /* hack : Changing UFST internal data - see above. */
1377 pIFS->fcCur.ssnum = RAW_GLYPH;
1378 }
1379 r->callback_error = 0;
1380 ff->char_data = (void *)notdef;
1381 ff->char_data_len = strlen(notdef);
1382 CGIFchIdptr(FSA (void *)&c1, (void *)notdef);
1383 code2 = CGIFchar_handle(FSA c1, &result, (SW16)0);
1384 if (code2 && code2 != ERR_fixed_space && code2 != ERR_bm_buff && code2 != ERR_bm_too_big) {
1385 ff->char_data = (void *)"space";
1386 ff->char_data_len = strlen("space");
1387 CGIFchIdptr(FSA (void *)&c1, (void *)"space");
1388 code2 = CGIFchar_handle(FSA c1, &result, (SW16)0);
1389 }
1390 if (!code2 || code2 == ERR_fixed_space) {
1391 code = code2;
1392 }
1393 pIFS->fcCur.ssnum = ssnum;
1394 }
1395 ff->char_data = client_char_data;
1396 ff->char_data_len = client_char_data_len;
1397
1398 #if !UFST_REENTRANT
1399 static_server_ptr_for_ufst_callback = 0;
1400 #endif
1401 r->ff = 0;
1402 release_glyphs(r, (ufst_common_font_data *)ff->server_font_data);
1403 if (code != ERR_fixed_space && code != 0)
1404 return code;
1405 if (r->callback_error != 0)
1406 return r->callback_error;
1407 if (format == FC_BITMAP_TYPE) {
1408 IFBITMAP *pbm = (IFBITMAP *)result;
1409
1410 du_emx = pbm->du_emx;
1411 du_emy = pbm->du_emy;
1412 r->char_data = pbm;
1413 r->bRaster = TRUE;
1414
1415 design_escapement[0] = pbm->escapement;
1416
1417 #if UFST_VERSION_MAJOR >= 6 && UFST_VERSION_MINOR >= 2
1418
1419 design_bbox[0] = pIFS->glyphMetricsDU.bbox.BBox[0];
1420 design_bbox[1] = pIFS->glyphMetricsDU.bbox.BBox[1];
1421 design_bbox[2] = pIFS->glyphMetricsDU.bbox.BBox[2];
1422 design_bbox[3] = pIFS->glyphMetricsDU.bbox.BBox[3];
1423 if (d->font_type != FC_FCO_TYPE) {
1424 design_escapement[0] = pIFS->glyphMetricsDU.aw.x;
1425 design_escapement[1] = pIFS->glyphMetricsDU.aw.y;
1426 }
1427 #endif
1428
1429 } else {
1430 IFOUTLINE *pol = (IFOUTLINE *)result;
1431
1432 design_escapement[0] = pol->escapement;
1433 du_emx = pol->du_emx;
1434 du_emy = pol->du_emy;
1435 r->char_data = (IFOUTLINE *)result;
1436 }
1437 #if 1 /* UFST 5.0 */
1438 if (USBOUNDBOX && d->font_type == FC_FCO_TYPE) {
1439 if (pIFS->USBBOXorigScaleFactor /* fixme : Must we check this ? */
1440 && pIFS->USBBOXorigScaleFactor != pIFS->USBBOXscaleFactor) {
1441 /* See fco_make_gaso_and_stats in fc_if.c . Debugged with hollow box in Helvetica. */
1442 /* Fixme : this looses a precision, an UFST bug has been reported. */
1443 int w = pIFS->USBBOXorigScaleFactor / 2;
1444
1445 design_bbox[0] = pIFS->USBBOXxmin * pIFS->USBBOXscaleFactor / pIFS->USBBOXorigScaleFactor;
1446 design_bbox[1] = pIFS->USBBOXymin * pIFS->USBBOXscaleFactor / pIFS->USBBOXorigScaleFactor;
1447 design_bbox[2] = (pIFS->USBBOXxmax * pIFS->USBBOXscaleFactor + w) / pIFS->USBBOXorigScaleFactor;
1448 design_bbox[3] = (pIFS->USBBOXymax * pIFS->USBBOXscaleFactor + w) / pIFS->USBBOXorigScaleFactor;
1449 } else {
1450 design_bbox[0] = pIFS->USBBOXxmin;
1451 design_bbox[1] = pIFS->USBBOXymin;
1452 design_bbox[2] = pIFS->USBBOXxmax;
1453 design_bbox[3] = pIFS->USBBOXymax;
1454 }
1455 } else {
1456 #if UFST_VERSION_MAJOR >= 6 && UFST_VERSION_MINOR >= 2
1457 #else
1458 /* fixme: UFST 5.0 doesn't provide this data.
1459 Stubbing with Em box.
1460 Non-FCO fonts may be cropped if a glyph goes outside Em box
1461 (or occupy negative coordinates, such as 'y'.).
1462 Non-FCO fonts may be uncached if Em box is much bigger than the glyph.
1463 */
1464 design_bbox[0] = 0;
1465 design_bbox[1] = 0;
1466 design_bbox[2] = du_emx;
1467 design_bbox[3] = du_emy;
1468 #endif
1469 }
1470 #endif
1471 { /* UFST performs a dual rounding of the glyph origin : first
1472 the scaled glyph design origin is rounded to pixels with floor(x + 0.5),
1473 second the glyph position is rounded to pixels with floor(x + 0.5).
1474 Ghostscript rounds with floor(x) due to the pixel-center-inside rule.
1475
1476 A right way would be to specify the half pixel offset to the glyph
1477 origin for the rendering glyph, but UFST has no interface for doing that.
1478 Instead that, to prevent a possible cropping while copying a glyph to cache cell,
1479 we expand the design bbox in a value of a pixel size.
1480 We could not determine the necessary expansion theoretically,
1481 and choosen expansion coefficients empirically,
1482 which appears equal to 2 pixels.
1483
1484 fixme: Actually the expansion is the FONTCONTEXT property,
1485 so it could be computed at once when the scaled font is created.
1486 */
1487 const double expansion_x = 2, expansion_y = 2; /* pixels */ /* adesso5.pdf */
1488 const double XX = r->tran_xx * (r->fc.s.m2.xworld_res >> 16) / 72 / du_emx;
1489 const double XY = r->tran_xy * (r->fc.s.m2.yworld_res >> 16) / 72 / du_emy;
1490 const double YX = r->tran_yx * (r->fc.s.m2.xworld_res >> 16) / 72 / du_emx;
1491 const double YY = r->tran_yy * (r->fc.s.m2.yworld_res >> 16) / 72 / du_emy;
1492 const double det = XX * YY - XY * YX;
1493 const double deta = det < 0 ? -det : det;
1494
1495 if (deta > 0.0000000001) {
1496 const double xx = YY / det, xy = -XY / det;
1497 const double yx = -YX / det, yy = XX / det;
1498 const double dx = -(expansion_x * xx + expansion_y * xy);
1499 const double dy = -(expansion_x * yx + expansion_y * yy);
1500 const SL32 dxa = (SL32)((dx < 0 ? -dx : dx) + 0.5);
1501 const SL32 dya = (SL32)((dy < 0 ? -dy : dy) + 0.5);
1502
1503 design_bbox[0] -= dxa;
1504 design_bbox[1] -= dya;
1505 design_bbox[2] += dxa;
1506 design_bbox[3] += dya;
1507 }
1508 }
1509 set_metrics(r, metrics, design_bbox, design_escapement, du_emx, du_emy);
1510 if (code == ERR_fixed_space)
1511 release_char_data_inline(r);
1512 return 0;
1513 }
1514
get_char_outline_metrics(FAPI_server * server,FAPI_font * ff,FAPI_char_ref * c,FAPI_metrics * metrics)1515 static FAPI_retcode get_char_outline_metrics(FAPI_server *server, FAPI_font *ff, FAPI_char_ref *c, FAPI_metrics *metrics)
1516 { fapi_ufst_server *r = If_to_I(server);
1517
1518 release_char_data_inline(r);
1519 return get_char(r, ff, c, NULL, metrics, FC_CUBIC_TYPE);
1520 /* UFST cannot render enough metrics information without generating raster or outline.
1521 r->char_data keeps an outline after calling this function.
1522 */
1523 }
1524
get_char_outline(FAPI_server * server,FAPI_path * p)1525 static FAPI_retcode get_char_outline(FAPI_server *server, FAPI_path *p)
1526 { fapi_ufst_server *r = If_to_I(server);
1527
1528 return export_outline(r, (IFOUTLINE *)r->char_data, p);
1529 }
1530
get_char_raster_metrics(FAPI_server * server,FAPI_font * ff,FAPI_char_ref * c,FAPI_metrics * metrics)1531 static FAPI_retcode get_char_raster_metrics(FAPI_server *server, FAPI_font *ff, FAPI_char_ref *c, FAPI_metrics *metrics)
1532 {
1533 fapi_ufst_server *r = If_to_I(server);
1534 int code;
1535
1536 release_char_data_inline(r);
1537 code = get_char(r, ff, c, NULL, metrics, FC_BITMAP_TYPE);
1538 if (code == ERR_bm_buff || code == ERR_bm_too_big) /* Too big character ? */
1539 return (e_VMerror);
1540 return code;
1541 /* UFST cannot render enough metrics information without generating raster or outline.
1542 r->char_data keeps a raster after calling this function.
1543 */
1544 }
1545
get_char_width(FAPI_server * server,FAPI_font * ff,FAPI_char_ref * c,FAPI_metrics * metrics)1546 static FAPI_retcode get_char_width(FAPI_server *server, FAPI_font *ff, FAPI_char_ref *c, FAPI_metrics *metrics)
1547 {
1548 fapi_ufst_server *r = If_to_I(server);
1549 int code;
1550
1551 release_char_data_inline(r);
1552 code = get_char(r, ff, c, NULL, metrics, server->use_outline ? FC_CUBIC_TYPE : FC_BITMAP_TYPE);
1553 if (code == ERR_bm_buff || code == ERR_bm_too_big) /* Too big character ? */
1554 return (e_VMerror);
1555 return code;
1556 /* UFST cannot render enough metrics information without generating raster or outline.
1557 r->char_data keeps a raster after calling this function.
1558 */
1559 }
1560
1561
get_char_raster(FAPI_server * server,FAPI_raster * rast)1562 static FAPI_retcode get_char_raster(FAPI_server *server, FAPI_raster *rast)
1563 { fapi_ufst_server *r = If_to_I(server);
1564
1565 if (!r->bRaster)
1566 return e_limitcheck;
1567 else if (r->char_data == NULL) {
1568 rast->height = rast->width = rast->line_step = 0;
1569 rast->p = 0;
1570 } else {
1571 IFBITMAP *pbm = (IFBITMAP *)r->char_data;
1572 rast->p = pbm->bm;
1573 rast->height = pbm->top_indent + pbm->black_depth;
1574 rast->width = pbm->left_indent + pbm->black_width;
1575 rast->line_step = pbm->width;
1576 rast->left_indent = pbm->left_indent;
1577 rast->top_indent = pbm->top_indent;
1578 rast->black_width = pbm->black_width;
1579 rast->black_height = pbm->black_depth;
1580 if (rast->width != 0) {
1581 rast->orig_x = pbm->xorigin;
1582 rast->orig_y = pbm->yorigin;
1583 } else
1584 rast->orig_x = rast->orig_y = 0;
1585 }
1586 return 0;
1587 }
1588
release_char_data(FAPI_server * server)1589 static FAPI_retcode release_char_data(FAPI_server *server)
1590 { fapi_ufst_server *r = If_to_I(server);
1591
1592 release_char_data_inline(r);
1593 return 0;
1594 }
1595
release_fco(fapi_ufst_server * r,SW16 fcHandle)1596 static void release_fco(fapi_ufst_server *r, SW16 fcHandle)
1597 {
1598 fco_list_elem **e;
1599
1600 if(gx_UFST_find_static_fco_handle(fcHandle) != NULL)
1601 return;
1602 for (e = &r->fco_list; *e != 0; )
1603 if ((*e)->fcHandle == fcHandle && (--(*e)->open_count) == 0) {
1604 fco_list_elem *ee = *e;
1605 FSA_FROM_SERVER;
1606
1607 *e = ee->next;
1608 CGIFfco_Close(FSA ee->fcHandle);
1609 gs_free(r->mem, ee->file_path, 0, 0, "fco_file_path");
1610 gs_free(r->mem, ee, 0, 0, "fco_list_elem");
1611 } else
1612 e = &(*e)->next;
1613 }
1614
FAPIU_release_typeface(FAPI_server * server,void * font_data)1615 static FAPI_retcode FAPIU_release_typeface(FAPI_server *server, void *font_data)
1616 { fapi_ufst_server *r = If_to_I(server);
1617 ufst_common_font_data *d;
1618 FAPI_retcode code = 0;
1619 FSA_FROM_SERVER;
1620
1621 release_char_data_inline(r);
1622 if (font_data == 0)
1623 return 0;
1624 d = (ufst_common_font_data *)font_data;
1625 #if 0
1626 prepare_typeface(r, d);
1627 if (d->is_disk_font)
1628 code = CGIFhdr_font_purge(FSA &r->fc);
1629 else
1630 code = CGIFfont_purge(FSA &r->fc);
1631 #endif
1632
1633 release_glyphs(r, d);
1634 release_fco(r, (SW16)(d->font_id >> 16));
1635 gs_free(r->mem, font_data, 0, 0, "ufst font data");
1636 return code;
1637 }
1638
check_cmap_for_GID(FAPI_server * server,uint * index)1639 static FAPI_retcode check_cmap_for_GID(FAPI_server *server, uint *index)
1640 {
1641 return 0;
1642 }
1643
1644 /* --------------------- The plugin definition : ------------------------- */
1645
1646 static void gs_fapiufst_finit(i_plugin_instance *instance, i_plugin_client_memory *mem);
1647
1648 static const i_plugin_descriptor ufst_descriptor = {
1649 "FAPI",
1650 "UFST",
1651 gs_fapiufst_finit
1652 };
1653
1654 static const FAPI_server If0 = {
1655 { &ufst_descriptor
1656 },
1657 16, /* frac_shift */
1658 {gs_no_id},
1659 {0},
1660 0,
1661 false,
1662 {1, 0, 0, 1, 0, 0},
1663 ensure_open,
1664 get_scaled_font,
1665 get_decodingID,
1666 get_font_bbox,
1667 get_font_proportional_feature,
1668 can_retrieve_char_by_name,
1669 can_replace_metrics,
1670 get_fontmatrix,
1671 get_char_width,
1672 get_char_raster_metrics,
1673 get_char_raster,
1674 get_char_outline_metrics,
1675 get_char_outline,
1676 release_char_data,
1677 FAPIU_release_typeface,
1678 check_cmap_for_GID
1679 };
1680
fapiu_make_string(i_ctx_t * i_ctx_p,const char * str,ref * obj)1681 static int fapiu_make_string (i_ctx_t *i_ctx_p, const char *str, ref *obj)
1682 {
1683 int len = strlen(str);
1684 byte *sbody;
1685
1686 sbody = ialloc_string(len, "fapiu_make_string");
1687 if (!sbody) {
1688 return(e_VMerror);
1689 }
1690 memcpy (sbody, str, len);
1691
1692 make_string(obj, a_all | icurrent_space, len, sbody);
1693
1694 return(0);
1695 }
1696
1697 plugin_instantiation_proc(gs_fapiufst_instantiate); /* check prototype */
1698
gs_fapiufst_instantiate(i_plugin_client_memory * client_mem,i_plugin_instance ** p_instance)1699 int gs_fapiufst_instantiate(i_plugin_client_memory *client_mem, i_plugin_instance **p_instance)
1700 {
1701 fapi_ufst_server *r = (fapi_ufst_server *)client_mem->alloc(client_mem, sizeof(fapi_ufst_server), "fapi_ufst_server");
1702 i_ctx_t *i_ctx_p = NULL;
1703 gs_main_instance *inst;
1704 ref entry;
1705 char tmppath[gp_file_name_sizeof];
1706 int code = 0;
1707
1708 if (r == 0)
1709 return e_Fatal;
1710 memset(r, 0, sizeof(*r));
1711 r->If = If0;
1712
1713 code = gs_memory_chunk_wrap(&(r->mem), client_mem->client_data);
1714 if (code != 0) {
1715 return(code);
1716 }
1717
1718 *p_instance = &r->If.ig;
1719
1720 inst = get_minst_from_memory((const gs_memory_t *)(client_mem->client_data));
1721 i_ctx_p = inst->i_ctx_p;
1722
1723 /* The following entries will get overwritten if the user specifies alternative settings
1724 * on the command line.
1725 */
1726 strncpy(tmppath, UFSTFONTDIR, gp_file_name_sizeof);
1727 strncat(tmppath, UFST_PlugIn_Path, gp_file_name_sizeof - strlen(tmppath));
1728
1729 fapiu_make_string (i_ctx_p, (const char *)tmppath, &entry);
1730 (void)dict_put_string(systemdict, UFST_PlugIn_Str, &entry, NULL);
1731
1732 strncpy(tmppath, UFSTFONTDIR, gp_file_name_sizeof);
1733 strncat(tmppath, FCOfontfilePath, gp_file_name_sizeof - strlen(tmppath));
1734
1735 fapiu_make_string (i_ctx_p, (const char *)tmppath, &entry);
1736 (void)dict_put_string(systemdict, FCOfontfileStr, &entry, NULL);
1737
1738 strncpy(tmppath, UFSTFONTDIR, gp_file_name_sizeof);
1739 strncat(tmppath, FCOfontfile2Path, gp_file_name_sizeof - strlen(tmppath));
1740
1741 fapiu_make_string (i_ctx_p, (const char *)tmppath, &entry);
1742 (void)dict_put_string(systemdict, FCOfontfile2Str, &entry, NULL);
1743
1744 fapiu_make_string (i_ctx_p, FAPIfontmap, &entry);
1745 (void)dict_put_string(systemdict, FAPIfontmapStr, &entry, NULL);
1746
1747 return 0;
1748 }
1749
1750 #ifndef UFST_MEMORY_CHECKING
1751 #define UFST_MEMORY_CHECKING 0
1752 #endif
1753
1754 #if UFST_MEMORY_CHECKING
1755 extern unsigned long maxmem;
1756 #endif
1757
gs_fapiufst_finit(i_plugin_instance * this,i_plugin_client_memory * mem)1758 static void gs_fapiufst_finit(i_plugin_instance *this, i_plugin_client_memory *mem)
1759 { fapi_ufst_server *r = (fapi_ufst_server *)this;
1760 FSA_FROM_SERVER;
1761
1762 #if UFST_MEMORY_CHECKING
1763 dprintf1("UFST used %Lf kb\n", ((long double)maxmem) / 1024);
1764 #endif
1765
1766 if (r->If.ig.d != &ufst_descriptor)
1767 return; /* safety */
1768 #if 0 /* Disabled against a reentrancy problem
1769 in a single language build for host-based applications. */
1770 gx_set_UFST_Callbacks(NULL, NULL, NULL);
1771 #endif
1772 release_char_data_inline(r);
1773 if (r->bInitialized && !r->ufst_is_singleton)
1774 gx_UFST_fini();
1775 if (r->param) {
1776 gs_free (r->mem, r->param, 0, 0, "server_params");
1777 }
1778 gs_memory_chunk_release (r->mem);
1779
1780 mem->free(mem, r, "fapi_ufst_server");
1781 }
1782