/src/ghostpdl/pcl/pl/pllfont.c
Line | Count | Source |
1 | | /* Copyright (C) 2001-2023 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 | | |
17 | | /* pclfont.c */ |
18 | | /* PCL5 font preloading */ |
19 | | #include "ctype_.h" |
20 | | #include "stdio_.h" |
21 | | #include "string_.h" |
22 | | #include "gx.h" |
23 | | #include "gxiodev.h" |
24 | | #include "gp.h" |
25 | | #include "gsccode.h" |
26 | | #include "gserrors.h" |
27 | | #include "gsmatrix.h" |
28 | | #include "gsutil.h" |
29 | | #include "gxfont.h" |
30 | | #include "gxfont42.h" |
31 | | #include "stream.h" |
32 | | #include "strmio.h" |
33 | | #include "plfont.h" |
34 | | #include "pldict.h" |
35 | | #include "pllfont.h" |
36 | | #include "plftable.h" |
37 | | #include "plvalue.h" |
38 | | #include "plvocab.h" |
39 | | #include "gxfapi.h" |
40 | | #include "plfapi.h" |
41 | | #include "plufstlp.h" |
42 | | |
43 | | |
44 | | extern const char gp_file_name_list_separator; |
45 | | |
46 | | /* Load some built-in fonts. This must be done at initialization time, but |
47 | | * after the state and memory are set up. Return an indication of whether |
48 | | * at least one font was successfully loaded. XXX The existing code is more |
49 | | * than a bit of a hack. Approach: expect to find some fonts in one or more |
50 | | * of a given list of directories with names *.ttf. Load whichever ones are |
51 | | * found in the table below. Probably very little of this code can be |
52 | | * salvaged for later. |
53 | | */ |
54 | | |
55 | | /* get the windows truetype font file name */ |
56 | | #define WINDOWSNAME 4 |
57 | 862k | #define PSNAME 6 |
58 | | |
59 | | static int |
60 | | get_name_from_tt_file(stream * tt_file, gs_memory_t * mem, |
61 | | char *pfontfilename, int nameoffset) |
62 | 862k | { |
63 | | /* check if an open file a ttfile saving and restoring the file position */ |
64 | 862k | long pos; /* saved file position */ |
65 | 862k | unsigned long len; |
66 | 862k | char *ptr = pfontfilename; |
67 | 862k | byte *ptt_font_data; |
68 | | |
69 | 862k | if ((pos = sftell(tt_file)) < 0) |
70 | 0 | return -1; |
71 | | /* seek to end and get the file length and allocate a buffer |
72 | | for the entire file */ |
73 | 862k | if (sfseek(tt_file, 0L, SEEK_END)) |
74 | 0 | return -1; |
75 | 862k | len = sftell(tt_file); |
76 | | |
77 | | /* allocate a buffer for the entire file */ |
78 | 862k | ptt_font_data = gs_alloc_bytes(mem, len, "get_name_from_tt_file"); |
79 | 862k | if (ptt_font_data == NULL) |
80 | 0 | return_error(gs_error_VMerror); |
81 | | |
82 | | /* seek back to the beginning of the file and read the data |
83 | | into the buffer */ |
84 | 862k | if ((sfseek(tt_file, 0L, SEEK_SET) == 0) && (sfread(ptt_font_data, 1, len, tt_file) == len)); /* ok */ |
85 | 0 | else { |
86 | 0 | gs_free_object(mem, ptt_font_data, "get_name_from_tt_file"); |
87 | 0 | return -1; |
88 | 0 | } |
89 | | |
90 | 862k | { |
91 | | /* find the "name" table */ |
92 | 862k | byte *pnum_tables_data = ptt_font_data + 4; |
93 | 862k | byte *ptable_directory_data = ptt_font_data + 12; |
94 | 862k | int table; |
95 | | |
96 | 10.8M | for (table = 0; table < pl_get_uint16(pnum_tables_data); table++) |
97 | 10.8M | if (!memcmp(ptable_directory_data + (table * 16), "name", 4)) { |
98 | 862k | unsigned int offset = |
99 | 862k | pl_get_uint32(ptable_directory_data + (table * 16) + 8); |
100 | 862k | byte *name_table = ptt_font_data + offset; |
101 | | /* the offset to the string pool */ |
102 | 862k | unsigned short storageOffset = pl_get_uint16(name_table + 4); |
103 | 862k | byte *name_recs = name_table + 6; |
104 | | |
105 | 862k | { |
106 | | /* 4th entry in the name table - the complete name */ |
107 | 862k | unsigned short length = |
108 | 862k | pl_get_uint16(name_recs + (12 * nameoffset) + 8); |
109 | 862k | unsigned short offset = |
110 | 862k | pl_get_uint16(name_recs + (12 * nameoffset) + 10); |
111 | 862k | int k; |
112 | | |
113 | 16.8M | for (k = 0; k < length; k++) { |
114 | | /* hack around unicode if necessary */ |
115 | 15.9M | int c = name_table[storageOffset + offset + k]; |
116 | | |
117 | 15.9M | if (isprint(c)) |
118 | 15.8M | *ptr++ = (char)c; |
119 | 15.9M | } |
120 | 862k | } |
121 | 862k | break; |
122 | 862k | } |
123 | 862k | } |
124 | | /* free up the data and restore the file position */ |
125 | 862k | gs_free_object(mem, ptt_font_data, "get_name_from_tt_file"); |
126 | 862k | if (sfseek(tt_file, pos, SEEK_SET) < 0) |
127 | 0 | return -1; |
128 | | /* null terminate the fontname string and return success. Note |
129 | | the string can be 0 length if no fontname was found. */ |
130 | 862k | *ptr = '\0'; |
131 | | |
132 | | /* trim trailing white space */ |
133 | 862k | { |
134 | 862k | int i = strlen(pfontfilename); |
135 | | |
136 | 862k | while (--i >= 0) { |
137 | 862k | if (!isspace(pfontfilename[i])) |
138 | 862k | break; |
139 | 862k | } |
140 | 862k | pfontfilename[++i] = '\0'; |
141 | 862k | } |
142 | | |
143 | 862k | return 0; |
144 | 862k | } |
145 | | |
146 | | #ifdef DEBUG |
147 | | static void |
148 | | check_resident_ufst_fonts(pl_dict_t * pfontdict, |
149 | | bool use_unicode_names_for_keys, gs_memory_t * mem) |
150 | | { |
151 | | int j; |
152 | | |
153 | | for (j = 0; |
154 | | *pl_built_in_resident_font_table[j].full_font_name[AGFANAME] != 0 |
155 | | && j < pl_built_in_resident_font_table_count; j++) { |
156 | | void *value; |
157 | | |
158 | | /* lookup unicode key in the resident table */ |
159 | | if (use_unicode_names_for_keys) { |
160 | | if (!pl_dict_lookup(pfontdict, |
161 | | (const byte *)pl_built_in_resident_font_table[j]. |
162 | | unicode_fontname, |
163 | | sizeof(pl_built_in_resident_font_table[j].unicode_fontname), |
164 | | &value, true, |
165 | | NULL) /* return data ignored */ ) { |
166 | | int i; |
167 | | |
168 | | dmprintf(mem, "Font with unicode key: "); |
169 | | for (i = 0; |
170 | | i < |
171 | | sizeof(pl_built_in_resident_font_table[j].unicode_fontname) / |
172 | | sizeof(pl_built_in_resident_font_table[j].unicode_fontname[0]); i++) { |
173 | | dmprintf1(mem, "%c", |
174 | | (char)pl_built_in_resident_font_table[j].unicode_fontname[i]); |
175 | | } |
176 | | dmprintf1(mem, |
177 | | " not available in font dictionary, resident table position: %d\n", |
178 | | j); |
179 | | } |
180 | | } else { |
181 | | byte key[3]; |
182 | | |
183 | | key[2] = (byte) j; |
184 | | key[0] = key[1] = 0; |
185 | | if (!pl_dict_lookup(pfontdict, |
186 | | key, |
187 | | sizeof(key), |
188 | | &value, true, |
189 | | NULL) /* return data ignored */ ) |
190 | | dmprintf2(mem, |
191 | | "%s not available in font dictionary, resident table position: %d\n", |
192 | | (char *)pl_built_in_resident_font_table[j].full_font_name, j); |
193 | | } |
194 | | } |
195 | | return; |
196 | | } |
197 | | |
198 | | static void |
199 | | check_resident_fonts(pl_dict_t * pfontdict, gs_memory_t * mem) |
200 | | { |
201 | | int i; |
202 | | |
203 | | for (i = 0; |
204 | | *pl_built_in_resident_font_table[i].full_font_name[URWNAME] != 0 |
205 | | && i < pl_built_in_resident_font_table_count; i++) |
206 | | if (!pl_lookup_font_by_pjl_number(pfontdict, i)) { |
207 | | int j; |
208 | | |
209 | | dmprintf2(mem, "%s (entry %d) not found\n", |
210 | | pl_built_in_resident_font_table[i].full_font_name[URWNAME], i); |
211 | | dmprintf(mem, "pxl unicode name:"); |
212 | | for (j = 0; j < countof(pl_built_in_resident_font_table[i].unicode_fontname); j++) |
213 | | dmprintf1(mem, "'%c'", pl_built_in_resident_font_table[i].unicode_fontname[j]); |
214 | | dmprintf(mem, "\n"); |
215 | | } |
216 | | } |
217 | | #endif |
218 | | |
219 | | /* Load a built-in AGFA MicroType font */ |
220 | | static int |
221 | | pl_fill_in_mt_font(gs_font_base * pfont, pl_font_t * plfont, ushort handle, |
222 | | char *fco_path, gs_font_dir * pdir, gs_memory_t * mem, |
223 | | long unique_id) |
224 | 0 | { |
225 | 0 | int code = 0; |
226 | |
|
227 | 0 | if (pfont == 0 || plfont == 0) |
228 | 0 | code = gs_note_error(gs_error_VMerror); |
229 | 0 | else { /* Initialize general font boilerplate. */ |
230 | 0 | code = |
231 | 0 | pl_fill_in_font((gs_font *) pfont, plfont, pdir, mem, |
232 | 0 | "illegal_font"); |
233 | 0 | if (code >= 0) { /* Initialize MicroType font boilerplate. */ |
234 | 0 | plfont->header = 0; |
235 | 0 | plfont->header_size = 0; |
236 | 0 | plfont->scaling_technology = plfst_MicroType; |
237 | 0 | plfont->font_type = plft_Unicode; |
238 | 0 | plfont->large_sizes = true; |
239 | 0 | plfont->is_xl_format = false; |
240 | 0 | plfont->allow_vertical_substitutes = false; |
241 | |
|
242 | 0 | gs_make_identity(&pfont->FontMatrix); |
243 | 0 | pfont->FontMatrix.xx = pfont->FontMatrix.yy = 0.001f; |
244 | 0 | pfont->FontType = ft_MicroType; |
245 | 0 | pfont->BitmapWidths = true; |
246 | 0 | pfont->ExactSize = fbit_use_outlines; |
247 | 0 | pfont->InBetweenSize = fbit_use_outlines; |
248 | 0 | pfont->TransformedChar = fbit_use_outlines; |
249 | |
|
250 | 0 | pfont->FontBBox.p.x = pfont->FontBBox.p.y = |
251 | 0 | pfont->FontBBox.q.x = pfont->FontBBox.q.y = 0; |
252 | |
|
253 | 0 | uid_set_UniqueID(&pfont->UID, unique_id | ( ((long) handle) << 16)); |
254 | 0 | pfont->encoding_index = 1; /****** WRONG ******/ |
255 | 0 | pfont->nearest_encoding_index = 1; /****** WRONG ******/ |
256 | 0 | } |
257 | 0 | } |
258 | 0 | return (code); |
259 | 0 | } |
260 | | |
261 | | int |
262 | | pl_load_ufst_lineprinter(gs_memory_t * mem, pl_dict_t * pfontdict, |
263 | | gs_font_dir * pdir, int storage, |
264 | | bool use_unicode_names_for_keys) |
265 | 0 | { |
266 | 0 | int i; |
267 | |
|
268 | 0 | for (i = 0; |
269 | 0 | *pl_built_in_resident_font_table[i].full_font_name[AGFANAME] != 0 |
270 | 0 | && i < pl_built_in_resident_font_table_count; i++) { |
271 | 0 | if (pl_built_in_resident_font_table[i].params.typeface_family == 0) { |
272 | 0 | const byte *header = NULL; |
273 | 0 | const byte *char_data = NULL; |
274 | 0 | pl_font_t *pplfont = |
275 | 0 | pl_alloc_font(mem, "pl_load_ufst_lineprinter pplfont"); |
276 | 0 | gs_font_base *pfont = |
277 | 0 | gs_alloc_struct(mem, gs_font_base, &st_gs_font_base, |
278 | 0 | "pl_load_ufst_lineprinter pfont"); |
279 | 0 | int code; |
280 | |
|
281 | 0 | pl_get_ulp_character_data((byte **) & header, |
282 | 0 | (byte **) & char_data); |
283 | |
|
284 | 0 | if (!header || !char_data) { |
285 | 0 | return -1; |
286 | 0 | } |
287 | | |
288 | | /* these shouldn't happen during system setup */ |
289 | 0 | if (pplfont == 0 || pfont == 0) |
290 | 0 | return -1; |
291 | 0 | if (pl_fill_in_font |
292 | 0 | ((gs_font *) pfont, pplfont, pdir, mem, |
293 | 0 | "lineprinter_font") < 0) |
294 | 0 | return -1; |
295 | | |
296 | 0 | pl_fill_in_bitmap_font(pfont, gs_next_ids(mem, 1)); |
297 | 0 | pplfont->params = pl_built_in_resident_font_table[i].params; |
298 | 0 | memcpy(pplfont->character_complement, |
299 | 0 | pl_built_in_resident_font_table[i].character_complement, 8); |
300 | |
|
301 | 0 | if (use_unicode_names_for_keys) |
302 | 0 | code = pl_dict_put(pfontdict, |
303 | 0 | (const byte *)pl_built_in_resident_font_table[i].unicode_fontname, |
304 | 0 | sizeof(pl_built_in_resident_font_table[i].unicode_fontname), pplfont); |
305 | 0 | else { |
306 | 0 | byte key[3]; |
307 | |
|
308 | 0 | key[2] = (byte) i; |
309 | 0 | key[0] = key[1] = 0; |
310 | 0 | code = pl_dict_put(pfontdict, key, sizeof(key), pplfont); |
311 | 0 | } |
312 | 0 | if (code < 0) |
313 | 0 | return code; |
314 | 0 | pplfont->storage = storage; /* should be an internal font */ |
315 | 0 | pplfont->data_are_permanent = true; |
316 | 0 | pplfont->header = (byte *) header; |
317 | 0 | pplfont->font_type = plft_8bit_printable; |
318 | 0 | pplfont->scaling_technology = plfst_bitmap; |
319 | 0 | pplfont->is_xl_format = false; |
320 | 0 | pplfont->resolution.x = pplfont->resolution.y = 300; |
321 | |
|
322 | 0 | code = pl_font_alloc_glyph_table(pplfont, 256, mem, |
323 | 0 | "pl_load_ufst_lineprinter pplfont (glyph table)"); |
324 | 0 | if (code < 0) |
325 | 0 | return code; |
326 | | |
327 | 0 | while (1) { |
328 | |
|
329 | 0 | uint width = pl_get_uint16(char_data + 12); |
330 | 0 | uint height = pl_get_uint16(char_data + 14); |
331 | 0 | uint ccode_plus_header_plus_data = |
332 | 0 | 2 + 16 + (((width + 7) >> 3) * height); |
333 | 0 | uint ucode = |
334 | 0 | pl_map_MSL_to_Unicode(pl_get_uint16(char_data), 0); |
335 | 0 | int code = 0; |
336 | | |
337 | | /* NB this shouldn't happen but it does, should be |
338 | | looked at */ |
339 | 0 | if (ucode != 0xffff) |
340 | 0 | code = pl_font_add_glyph(pplfont, ucode, char_data + 2, ccode_plus_header_plus_data); |
341 | |
|
342 | 0 | if (code < 0) |
343 | | /* shouldn't happen */ |
344 | 0 | return -1; |
345 | | /* calculate the offset of the next character code in the table */ |
346 | 0 | char_data += ccode_plus_header_plus_data; |
347 | | |
348 | | /* char code 0 is end of table */ |
349 | 0 | if (pl_get_uint16(char_data) == 0) |
350 | 0 | break; |
351 | 0 | } |
352 | 0 | code = gs_definefont(pdir, (gs_font *) pfont); |
353 | 0 | if (code < 0) |
354 | | /* shouldn't happen */ |
355 | 0 | return -1; |
356 | 0 | } |
357 | 0 | } |
358 | 0 | return 0; |
359 | 0 | } |
360 | | |
361 | | |
362 | | static int |
363 | | pl_load_built_in_mtype_fonts(const char *pathname, gs_memory_t * mem, |
364 | | pl_dict_t * pfontdict, gs_font_dir * pdir, |
365 | | int storage, bool use_unicode_names_for_keys) |
366 | 105k | { |
367 | 105k | int i, k; |
368 | 105k | short status = 0; |
369 | 105k | int bSize; |
370 | 105k | byte key[3] = {0}; |
371 | 105k | char pthnm[1024]; |
372 | 105k | char *ufst_root_dir; |
373 | 105k | char *fco; |
374 | 105k | char *fco_start, *fco_lim; |
375 | 105k | pl_font_t *plfont = NULL; |
376 | 105k | gs_font *pfont = NULL; |
377 | 105k | gs_font_base *pbfont; |
378 | | |
379 | | /* don't load fonts more than once */ |
380 | 105k | if (pl_dict_length(pfontdict, true) > 0) |
381 | 94.8k | return 1; |
382 | | |
383 | 10.6k | if (!pl_fapi_ufst_available(mem)) { |
384 | 10.6k | return (0); |
385 | 10.6k | } |
386 | | |
387 | | |
388 | | /* |
389 | | * Open and install the various font collection objects. |
390 | | * |
391 | | * For each font collection object, step through the object until it is |
392 | | * exhausted, placing any fonts found in the built_in_fonts dictionary. |
393 | | * |
394 | | */ |
395 | 0 | ufst_root_dir = (char *)pl_fapi_ufst_get_font_dir(mem); |
396 | 0 | fco_start = fco = (char *)pl_fapi_ufst_get_fco_list(mem); |
397 | 0 | fco_lim = fco_start + strlen(fco_start) + 1; |
398 | |
|
399 | 0 | for (k = 0; fco < fco_lim && strlen(fco) > 0; k++) { |
400 | 0 | status = 0; |
401 | | /* build and open (get handle) for the k'th fco file name */ |
402 | 0 | gs_strlcpy((char *)pthnm, ufst_root_dir, sizeof pthnm); |
403 | |
|
404 | 0 | for (i = 2; fco[i] != gp_file_name_list_separator && (&fco[i]) < fco_lim - 1; i++) |
405 | 0 | ; |
406 | |
|
407 | 0 | strncat(pthnm, fco, i); |
408 | 0 | fco += (i + 1); |
409 | | |
410 | | /* enumerat the files in this fco */ |
411 | 0 | for (i = 0; status == 0; i++, key[2] += 1) { |
412 | 0 | char *pname = NULL; |
413 | | |
414 | | /* If we hit a font we're not going to use, we'll reuse the allocated |
415 | | * memory. |
416 | | */ |
417 | 0 | if (!plfont) { |
418 | |
|
419 | 0 | pbfont = |
420 | 0 | gs_alloc_struct(mem, gs_font_base, &st_gs_font_base, |
421 | 0 | "pl_mt_load_font(gs_font_base)"); |
422 | 0 | plfont = pl_alloc_font(mem, "pl_mt_load_font(pl_font_t)"); |
423 | 0 | if (!pbfont || !plfont) { |
424 | 0 | gs_free_object(mem, plfont, "pl_mt_load_font(pl_font_t)"); |
425 | 0 | gs_free_object(mem, pfont, |
426 | 0 | "pl_mt_load_font(gs_font_base)"); |
427 | 0 | dmprintf1(mem, "VM error for built-in font %d", i); |
428 | 0 | continue; |
429 | 0 | } |
430 | 0 | } |
431 | 0 | pfont = (gs_font *) pbfont; |
432 | |
|
433 | 0 | status = |
434 | 0 | pl_fill_in_mt_font(pbfont, plfont, i, pthnm, pdir, mem, i); |
435 | 0 | if (status < 0) { |
436 | 0 | dmprintf2(mem, "Error %d for built-in font %d", status, i); |
437 | 0 | continue; |
438 | 0 | } |
439 | | |
440 | 0 | status = |
441 | 0 | pl_fapi_passfont(plfont, i, (char *)"UFST", pthnm, NULL, 0); |
442 | |
|
443 | 0 | if (status != 0) { |
444 | | #ifdef DEBUG |
445 | | dmprintf1(mem, "CGIFfco_Access error %d\n", status); |
446 | | #endif |
447 | 0 | } else { |
448 | 0 | int font_number = 0; |
449 | | /* unfortunately agfa has 2 fonts named symbol. We |
450 | | believe the font with internal number, NB, NB, NB */ |
451 | 0 | char *symname = (char *)"SymbPS"; |
452 | 0 | int j; |
453 | 0 | uint spaceBand; |
454 | 0 | uint scaleFactor; |
455 | 0 | bool used = false; |
456 | 0 | int code = 0; |
457 | | |
458 | | /* For Microtype fonts, once we get here, these |
459 | | * pl_fapi_get*() calls cannot fail, so we can |
460 | | * safely ignore the return value |
461 | | */ |
462 | 0 | (void)pl_fapi_get_mtype_font_name(pfont, NULL, &bSize); |
463 | |
|
464 | 0 | pname = |
465 | 0 | (char *)gs_alloc_bytes(mem, bSize, |
466 | 0 | "pl_mt_load_font: font name buffer"); |
467 | 0 | if (!pname) { |
468 | 0 | dmprintf1(mem, "VM Error for built-in font %d", i); |
469 | 0 | continue; |
470 | 0 | } |
471 | | |
472 | 0 | (void)pl_fapi_get_mtype_font_name(pfont, (byte *) pname, |
473 | 0 | &bSize); |
474 | |
|
475 | 0 | (void)pl_fapi_get_mtype_font_number(pfont, &font_number); |
476 | 0 | (void)pl_fapi_get_mtype_font_spaceBand(pfont, &spaceBand); |
477 | 0 | (void)pl_fapi_get_mtype_font_scaleFactor(pfont, &scaleFactor); |
478 | |
|
479 | 0 | if (font_number == 24463) { |
480 | 0 | gs_free_object(mem, pname, |
481 | 0 | "pl_mt_load_font: font name buffer"); |
482 | 0 | pname = symname; |
483 | 0 | } |
484 | |
|
485 | 0 | for (j = 0; *pl_built_in_resident_font_table[j].full_font_name[AGFANAME]; j++) { |
486 | 0 | if (strcmp |
487 | 0 | ((char *)pl_built_in_resident_font_table[j].full_font_name[AGFANAME], |
488 | 0 | (char *)pname) != 0) |
489 | 0 | continue; |
490 | | |
491 | | #ifdef DEBUG |
492 | | if (gs_debug_c('=')) |
493 | | dmprintf2(mem, "Loading %s from fco %s\n", pname, |
494 | | pthnm); |
495 | | #endif |
496 | | /* Record the differing points per inch value |
497 | | for Intellifont derived fonts. */ |
498 | | |
499 | 0 | if (scaleFactor == 8782) { |
500 | 0 | plfont->pts_per_inch = 72.307f; |
501 | 0 | } |
502 | |
|
503 | 0 | plfont->font_type = pl_built_in_resident_font_table[j].font_type; |
504 | 0 | plfont->storage = storage; |
505 | 0 | plfont->data_are_permanent = false; |
506 | 0 | plfont->params = pl_built_in_resident_font_table[j].params; |
507 | | |
508 | | /* |
509 | | * NB: though the TTFONTINFOTYPE structure has a |
510 | | * pcltChComp field, it is not filled in by the UFST |
511 | | * code (which just initializes it to 0). Hence, the |
512 | | * hard-coded information in the resident font |
513 | | * initialization structure is used. |
514 | | */ |
515 | 0 | memcpy(plfont->character_complement, |
516 | 0 | pl_built_in_resident_font_table[j].character_complement, 8); |
517 | |
|
518 | 0 | status = gs_definefont(pdir, (gs_font *) pfont); |
519 | 0 | if (status < 0) { |
520 | 0 | status = 0; |
521 | 0 | continue; |
522 | 0 | } |
523 | 0 | status = |
524 | 0 | pl_fapi_passfont(plfont, i, (char *)"UFST", pthnm, |
525 | 0 | NULL, 0); |
526 | 0 | if (status < 0) { |
527 | 0 | status = 0; |
528 | 0 | continue; |
529 | 0 | } |
530 | 0 | if (use_unicode_names_for_keys) |
531 | 0 | code = pl_dict_put(pfontdict, |
532 | 0 | (const byte *)pl_built_in_resident_font_table[j].unicode_fontname, |
533 | 0 | sizeof(pl_built_in_resident_font_table[j].unicode_fontname), |
534 | 0 | plfont); |
535 | 0 | else { |
536 | 0 | key[2] = (byte) j; |
537 | 0 | key[0] = key[1] = 0; |
538 | 0 | code = pl_dict_put(pfontdict, key, sizeof(key), plfont); |
539 | 0 | } |
540 | 0 | if (code < 0) |
541 | 0 | return code; |
542 | 0 | used = true; |
543 | 0 | } |
544 | | /* If we've stored the font, null the local reference */ |
545 | 0 | if (used) { |
546 | 0 | plfont = NULL; |
547 | 0 | pfont = NULL; |
548 | 0 | } |
549 | 0 | if (pname != symname) |
550 | 0 | gs_free_object(mem, pname, |
551 | 0 | "pl_mt_load_font: font name buffer"); |
552 | 0 | pname = NULL; |
553 | 0 | } |
554 | 0 | } |
555 | 0 | } /* end enumerate fco loop */ |
556 | | |
557 | 0 | gs_free_object(mem, plfont, "pl_mt_load_font(pl_font_t)"); |
558 | 0 | gs_free_object(mem, pfont, "pl_mt_load_font(gs_font_base)"); |
559 | | |
560 | | /* finally add lineprinter NB return code ignored */ |
561 | 0 | (void)pl_load_ufst_lineprinter(mem, pfontdict, pdir, storage, |
562 | 0 | use_unicode_names_for_keys); |
563 | |
|
564 | | #ifdef DEBUG |
565 | | if (gs_debug_c('=')) |
566 | | check_resident_ufst_fonts(pfontdict, use_unicode_names_for_keys, mem); |
567 | | #endif |
568 | |
|
569 | 0 | if (status == 0 || status == -10) |
570 | 0 | return (1); |
571 | | |
572 | 0 | return (0); |
573 | 0 | } |
574 | | |
575 | | |
576 | | /* NOTES ABOUT NB NB - if the font dir necessary */ |
577 | | int |
578 | | pl_load_built_in_fonts(const char *pathname, gs_memory_t * mem, |
579 | | pl_dict_t * pfontdict, gs_font_dir * pdir, |
580 | | int storage, bool use_unicode_names_for_keys) |
581 | 105k | { |
582 | 105k | const font_resident_t *residentp; |
583 | | /* get rid of this should be keyed by pjl font number */ |
584 | 105k | byte key[3]; |
585 | 105k | char path[1024]; |
586 | 105k | bool found; |
587 | 105k | bool found_any = false; |
588 | 105k | file_enum *fe; |
589 | 105k | int code = 0; |
590 | | |
591 | 105k | if ((code = |
592 | 105k | pl_load_built_in_mtype_fonts(pathname, mem, pfontdict, pdir, storage, |
593 | 105k | use_unicode_names_for_keys))) { |
594 | 94.8k | return (code); |
595 | 94.8k | } |
596 | | |
597 | | /* don't load fonts more than once */ |
598 | 10.6k | if (pl_dict_length(pfontdict, true) > 0) |
599 | 0 | return 1; |
600 | | |
601 | 10.6k | if (pathname == NULL) |
602 | 0 | return 0; |
603 | | |
604 | 10.6k | if (gs_strlcpy(path, pathname, sizeof(path)) >= sizeof(path)) |
605 | 0 | return 0; |
606 | | |
607 | 10.6k | if (gs_strlcat(path, "*", sizeof(path)) >= sizeof(path)) |
608 | 0 | return 0; |
609 | | |
610 | 10.6k | fe = gs_enumerate_files_init(mem, path, strlen(path)); |
611 | 10.6k | if (fe == NULL) |
612 | 0 | return 0; |
613 | | |
614 | | /* loop through the files */ |
615 | 873k | while ((code = gs_enumerate_files_next(mem, fe, path, sizeof(path) - 1)) >= 0) { |
616 | 862k | char buffer[1024]; |
617 | 862k | pl_font_t *plfont; |
618 | 862k | stream *in; |
619 | | |
620 | 862k | if (code > sizeof(path) - 1) { |
621 | 0 | dmprintf(mem, |
622 | 0 | "filename length exceeds file name storage buffer length\n"); |
623 | 0 | continue; |
624 | 0 | } |
625 | | /* null terminate the string */ |
626 | 862k | path[code] = '\0'; |
627 | | |
628 | 862k | in = sfopen(path, "r", mem); |
629 | 862k | if (in == NULL) { /* shouldn't happen */ |
630 | 0 | dmprintf1(mem, "cannot open file %s\n", path); |
631 | 0 | continue; |
632 | 0 | } |
633 | | |
634 | 862k | code = get_name_from_tt_file(in, mem, buffer, PSNAME); |
635 | 862k | if (code < 0) { |
636 | 0 | dmprintf1(mem, "input output failure on TrueType File %s\n", |
637 | 0 | path); |
638 | 0 | sfclose(in); |
639 | 0 | continue; |
640 | 0 | } |
641 | | |
642 | 862k | if (strlen(buffer) == 0) { |
643 | 0 | dmprintf1(mem, |
644 | 0 | "could not extract font file name from file %s\n", |
645 | 0 | path); |
646 | 0 | sfclose(in); |
647 | 0 | continue; |
648 | 0 | } |
649 | | |
650 | | /* lookup the font file name in the resident table */ |
651 | 862k | found = false; |
652 | 862k | for (residentp = pl_built_in_resident_font_table; |
653 | 88.8M | *residentp->full_font_name[URWNAME]; ++residentp) { |
654 | 87.9M | if (strcmp(buffer, residentp->full_font_name[URWNAME]) != 0) |
655 | 86.8M | continue; |
656 | | /* load the font file into memory. NOTE: this closes the file - argh... */ |
657 | 1.08M | if (pl_load_tt_font(in, pdir, mem, |
658 | 1.08M | gs_next_ids(mem, 1), &plfont, |
659 | 1.08M | buffer) < 0) { |
660 | | /* vm error */ |
661 | 0 | gs_enumerate_files_close(mem, fe); |
662 | 0 | return gs_throw1(0, |
663 | 0 | "An unrecoverable failure occurred while reading the resident font %s\n", |
664 | 0 | path); |
665 | 0 | } |
666 | | /* reopen the file */ |
667 | 1.08M | in = sfopen(path, "r", mem); |
668 | 1.08M | if (in == NULL) { |
669 | 0 | gs_free_object(mem, plfont->pfont, "pl_tt_load_font(gs_font_type42)"); |
670 | 0 | pl_free_tt_fontfile_buffer(mem, plfont->header); |
671 | 0 | gs_free_object(mem, plfont, "pl_tt_load_font(pl_font_t)"); |
672 | 0 | gs_enumerate_files_close(mem, fe); |
673 | 0 | return gs_throw1(0, |
674 | 0 | "An unrecoverable failure occurred while reading the resident font %s\n", |
675 | 0 | path); |
676 | 0 | } |
677 | | |
678 | 1.08M | plfont->storage = storage; |
679 | 1.08M | plfont->data_are_permanent = false; |
680 | | |
681 | | /* use the offset in the table as the pjl font number */ |
682 | | /* for unicode keying of the dictionary use the unicode |
683 | | font name, otherwise use the keys. */ |
684 | 1.08M | plfont->font_type = residentp->font_type; |
685 | 1.08M | plfont->params = residentp->params; |
686 | 1.08M | memcpy(plfont->character_complement, |
687 | 1.08M | residentp->character_complement, 8); |
688 | 1.08M | if (use_unicode_names_for_keys) |
689 | 260k | code = pl_dict_put(pfontdict, |
690 | 260k | (const byte *)residentp->unicode_fontname, |
691 | 260k | sizeof(residentp->unicode_fontname), |
692 | 260k | plfont); |
693 | 825k | else { |
694 | 825k | key[2] = (byte) (residentp - pl_built_in_resident_font_table); |
695 | 825k | key[0] = key[1] = 0; |
696 | 825k | code = pl_dict_put(pfontdict, key, sizeof(key), plfont); |
697 | | /* leave data stored in the file. NB this should be a fatal error also. */ |
698 | 825k | if ((code >= 0) && pl_store_resident_font_data_in_file |
699 | 825k | (path, mem, plfont) < 0) { |
700 | 0 | dmprintf1(mem, "%s could not store data", |
701 | 0 | path); |
702 | 0 | continue; |
703 | 0 | } |
704 | 825k | } |
705 | 1.08M | if (code < 0) { |
706 | | /* on error, pl_dict_put consumes plfont */ |
707 | 0 | continue; |
708 | 0 | } |
709 | 1.08M | found = true; |
710 | 1.08M | found_any = true; |
711 | 1.08M | } |
712 | 862k | sfclose(in); |
713 | | |
714 | | /* nothing found */ |
715 | 862k | if (!found) { |
716 | | #ifdef DEBUG |
717 | | if (gs_debug_c('=')) { |
718 | | dmprintf2(mem, |
719 | | "TrueType font %s in file %s not found in table\n", |
720 | | buffer, path); |
721 | | in = sfopen(path, "r", mem); |
722 | | code = |
723 | | get_name_from_tt_file(in, mem, buffer, WINDOWSNAME); |
724 | | sfclose(in); |
725 | | dmprintf1(mem, "Windows name %s\n", buffer); |
726 | | if (code < 0) |
727 | | return code; |
728 | | } |
729 | | #endif |
730 | 0 | } |
731 | 862k | } /* next file */ |
732 | | #ifdef DEBUG |
733 | | if (gs_debug_c('=')) |
734 | | check_resident_fonts(pfontdict, mem); |
735 | | #endif |
736 | 10.6k | return found_any; |
737 | 10.6k | } |
738 | | |
739 | | /* These are not implemented */ |
740 | | |
741 | | /* load simm fonts given a path */ |
742 | | int |
743 | | pl_load_simm_fonts(const char *pathname, gs_memory_t * mem, |
744 | | pl_dict_t * pfontdict, gs_font_dir * pdir, int storage) |
745 | 0 | { |
746 | | /* not implemented */ |
747 | 0 | return 0; |
748 | 0 | } |
749 | | |
750 | | /* load simm fonts given a path */ |
751 | | int |
752 | | pl_load_cartridge_fonts(const char *pathname, gs_memory_t * mem, |
753 | | pl_dict_t * pfontdict, gs_font_dir * pdir, |
754 | | int storage) |
755 | 0 | { |
756 | | /* not implemented */ |
757 | 0 | return 0; |
758 | 0 | } |