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