1 /* Copyright (C) 2001-2019 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., 1305 Grant Avenue - Suite 200, Novato,
13 CA 94945, U.S.A., +1(415)492-9861, for further information.
14 */
15
16
17 /* Font API client */
18
19 #include "stdlib.h" /* abs() */
20
21 #include "memory_.h"
22 #include "math_.h"
23 #include "stat_.h" /* include before definition of esp macro, bug 691123 */
24 #include "string_.h"
25 #include "ghost.h"
26 #include "gp.h"
27 #include "oper.h"
28 #include "gxdevice.h"
29 #include "gxfont.h"
30 #include "gxfont1.h"
31 #include "gxchar.h"
32 #include "gzpath.h"
33 #include "gxpath.h"
34 #include "gxfcache.h"
35 #include "gxchrout.h"
36 #include "gximask.h"
37 #include "gscoord.h"
38 #include "gspaint.h"
39 #include "gsfont.h"
40 #include "gspath.h"
41 #include "bfont.h"
42 #include "dstack.h"
43 #include "estack.h"
44 #include "ichar.h"
45 #include "idict.h"
46 #include "iname.h"
47 #include "ifont.h"
48 #include "icid.h"
49 #include "igstate.h"
50 #include "icharout.h"
51
52 #include "ifapi.h"
53 #include "iplugin.h"
54 #include "store.h"
55 #include "gzstate.h"
56 /* #include "gdevpsf.h" */
57 #include "stream.h" /* for files.h */
58 #include "gscrypt1.h"
59 #include "gxfcid.h"
60 #include "gsstype.h"
61 #include "gxchar.h" /* for st_gs_show_enum */
62 #include "ipacked.h" /* for packed_next */
63 #include "iddict.h"
64 #include "ifont42.h" /* for string_array_access_proc */
65 #include "gdebug.h"
66 #include "gsimage.h"
67 #include "gxcldev.h"
68 #include "gxdevmem.h"
69
70 #include "gxfapi.h"
71
72 /* -------------------------------------------------------- */
73
74 typedef struct sfnts_reader_s sfnts_reader;
75 struct sfnts_reader_s
76 {
77 ref *sfnts;
78 const gs_memory_t *memory;
79 const byte *p;
80 long index;
81 uint offset;
82 uint length;
83 bool error;
84 byte(*rbyte) (sfnts_reader *r);
85 ushort(*rword) (sfnts_reader *r);
86 ulong(*rlong) (sfnts_reader *r);
87 int (*rstring) (sfnts_reader *r, byte *v, int length);
88 void (*seek) (sfnts_reader *r, ulong pos);
89 };
90
91 static void
sfnts_next_elem(sfnts_reader * r)92 sfnts_next_elem(sfnts_reader *r)
93 {
94 ref s;
95 int code;
96
97 if (r->error)
98 return;
99 do {
100 r->index++;
101 code = array_get(r->memory, r->sfnts, r->index, &s);
102 if (code == gs_error_rangecheck) {
103 r->error |= 2;
104 }
105 else if (code < 0) {
106 r->error |= 1;
107 }
108 if (r->error)
109 return;
110 r->p = s.value.const_bytes;
111 r->length = r_size(&s) & ~(uint) 1; /* See Adobe Technical Note # 5012, section 4.2. */
112 } while (r->length == 0);
113 r->offset = 0;
114 }
115
116 static inline byte
sfnts_reader_rbyte_inline(sfnts_reader * r)117 sfnts_reader_rbyte_inline(sfnts_reader *r)
118 {
119 if (r->offset >= r->length)
120 sfnts_next_elem(r);
121 return (r->error ? 0 : r->p[r->offset++]);
122 }
123
124 static byte
sfnts_reader_rbyte(sfnts_reader * r)125 sfnts_reader_rbyte(sfnts_reader *r)
126 { /* old compiler compatibility */
127 return (sfnts_reader_rbyte_inline(r));
128 }
129
130 #define SFNTS_READER_RBYTE_TO_USHORT(r) ((ulong)sfnts_reader_rbyte_inline(r))
131
132 static ushort
sfnts_reader_rword(sfnts_reader * r)133 sfnts_reader_rword(sfnts_reader *r)
134 {
135 ushort retval;
136
137 retval = SFNTS_READER_RBYTE_TO_USHORT(r) << 8;
138 retval += SFNTS_READER_RBYTE_TO_USHORT(r);
139
140 return retval;
141 }
142
143 #undef SFNTS_READER_RBYTE_TO_USHORT
144
145 #define SFNTS_READER_RBYTE_TO_ULONG(r) ((ulong)sfnts_reader_rbyte_inline(r))
146
147 static ulong
sfnts_reader_rlong(sfnts_reader * r)148 sfnts_reader_rlong(sfnts_reader *r)
149 {
150 ulong retval;
151 retval = SFNTS_READER_RBYTE_TO_ULONG(r) << 24;
152 retval += SFNTS_READER_RBYTE_TO_ULONG(r) << 16;
153 retval += SFNTS_READER_RBYTE_TO_ULONG(r) << 8;
154 retval += SFNTS_READER_RBYTE_TO_ULONG(r);
155 return retval;
156 }
157
158 #undef SFNTS_READER_RWORD_TO_LONG
159
160 static int
sfnts_reader_rstring(sfnts_reader * r,byte * v,int length)161 sfnts_reader_rstring(sfnts_reader *r, byte *v, int length)
162 {
163 int rlength = length;
164
165 if (length <= 0)
166 return (0);
167 while (!r->error) {
168 int l = min(length, r->length - r->offset);
169
170 memcpy(v, r->p + r->offset, l);
171 length -= l;
172 r->offset += l;
173 if (length <= 0)
174 return (rlength);
175 v += l;
176 sfnts_next_elem(r);
177 }
178 return (rlength - length);
179 }
180
181 static void
sfnts_reader_seek(sfnts_reader * r,ulong pos)182 sfnts_reader_seek(sfnts_reader *r, ulong pos)
183 { /* fixme : optimize */
184 ulong skipped = 0;
185
186 r->index = -1;
187 sfnts_next_elem(r);
188 while (skipped + r->length < pos && !r->error) {
189 skipped += r->length;
190 sfnts_next_elem(r);
191 }
192 r->offset = pos - skipped;
193 }
194
195 static void
sfnts_reader_init(sfnts_reader * r,ref * pdr)196 sfnts_reader_init(sfnts_reader *r, ref *pdr)
197 {
198 r->rbyte = sfnts_reader_rbyte;
199 r->rword = sfnts_reader_rword;
200 r->rlong = sfnts_reader_rlong;
201 r->rstring = sfnts_reader_rstring;
202 r->seek = sfnts_reader_seek;
203 r->index = -1;
204 r->error = false;
205 if (r_type(pdr) != t_dictionary ||
206 dict_find_string(pdr, "sfnts", &r->sfnts) <= 0)
207 r->error = true;
208 sfnts_next_elem(r);
209 }
210
211 /* -------------------------------------------------------- */
212
213 typedef struct sfnts_writer_s sfnts_writer;
214 struct sfnts_writer_s
215 {
216 byte *buf, *p;
217 int buf_size;
218 void (*wbyte) (sfnts_writer *w, byte v);
219 void (*wword) (sfnts_writer *w, ushort v);
220 void (*wlong) (sfnts_writer *w, ulong v);
221 void (*wstring) (sfnts_writer *w, byte *v, int length);
222 };
223
224 static void
sfnts_writer_wbyte(sfnts_writer * w,byte v)225 sfnts_writer_wbyte(sfnts_writer *w, byte v)
226 {
227 if (w->buf + w->buf_size < w->p + 1)
228 return; /* safety */
229 w->p[0] = v;
230 w->p++;
231 }
232
233 static void
sfnts_writer_wword(sfnts_writer * w,ushort v)234 sfnts_writer_wword(sfnts_writer *w, ushort v)
235 {
236 if (w->buf + w->buf_size < w->p + 2)
237 return; /* safety */
238 w->p[0] = v / 256;
239 w->p[1] = v % 256;
240 w->p += 2;
241 }
242
243 static void
sfnts_writer_wlong(sfnts_writer * w,ulong v)244 sfnts_writer_wlong(sfnts_writer *w, ulong v)
245 {
246 if (w->buf + w->buf_size < w->p + 4)
247 return; /* safety */
248 w->p[0] = v >> 24;
249 w->p[1] = (v >> 16) & 0xFF;
250 w->p[2] = (v >> 8) & 0xFF;
251 w->p[3] = v & 0xFF;
252 w->p += 4;
253 }
254
255 static void
sfnts_writer_wstring(sfnts_writer * w,byte * v,int length)256 sfnts_writer_wstring(sfnts_writer *w, byte *v, int length)
257 {
258 if (w->buf + w->buf_size < w->p + length)
259 return; /* safety */
260 memcpy(w->p, v, length);
261 w->p += length;
262 }
263
264 static const sfnts_writer sfnts_writer_stub = {
265 0, 0, 0,
266 sfnts_writer_wbyte,
267 sfnts_writer_wword,
268 sfnts_writer_wlong,
269 sfnts_writer_wstring
270 };
271
272 /* -------------------------------------------------------- */
273
274 static inline bool
sfnts_need_copy_table(byte * tag)275 sfnts_need_copy_table(byte *tag)
276 {
277 return (memcmp(tag, "glyf", 4) && memcmp(tag, "glyx", 4) && /* Presents in files created by AdobePS5.dll Version 5.1.2 */
278 memcmp(tag, "loca", 4) && memcmp(tag, "locx", 4) && /* Presents in files created by AdobePS5.dll Version 5.1.2 */
279 memcmp(tag, "cmap", 4));
280 }
281
282 static void
sfnt_copy_table(sfnts_reader * r,sfnts_writer * w,int length)283 sfnt_copy_table(sfnts_reader *r, sfnts_writer *w, int length)
284 {
285 byte buf[1024];
286
287 while (length > 0 && !r->error) {
288 int l = min(length, sizeof(buf));
289
290 (void)r->rstring(r, buf, l);
291 w->wstring(w, buf, l);
292 length -= l;
293 }
294 }
295
296 static ulong
sfnts_copy_except_glyf(sfnts_reader * r,sfnts_writer * w)297 sfnts_copy_except_glyf(sfnts_reader *r, sfnts_writer *w)
298 { /* Note : TTC is not supported and probably is unuseful for Type 42. */
299 /* This skips glyf, loca and cmap from copying. */
300 struct
301 {
302 byte tag[4];
303 ulong checkSum, offset, offset_new, length;
304 } tables[30];
305 const ushort alignment = 4; /* Not sure, maybe 2 */
306 ulong version = r->rlong(r);
307 ushort num_tables = r->rword(r);
308 ushort i, num_tables_new = 0;
309 ushort searchRange, entrySelector = 0, rangeShift, v;
310 ulong size_new = 12;
311
312 r->rword(r); /* searchRange */
313 r->rword(r); /* entrySelector */
314 r->rword(r); /* rangeShift */
315 for (i = 0; i < num_tables; i++) {
316 if (r->error)
317 return 0;
318 (void)r->rstring(r, tables[i].tag, 4);
319 tables[i].checkSum = r->rlong(r);
320 tables[i].offset = r->rlong(r);
321 tables[i].length = r->rlong(r);
322 tables[i].offset_new = size_new;
323 if (sfnts_need_copy_table(tables[i].tag)) {
324 num_tables_new++;
325 size_new +=
326 (tables[i].length + alignment - 1) / alignment * alignment;
327 }
328 }
329 size_new += num_tables_new * 16;
330 if (w == 0)
331 return size_new;
332
333 searchRange = v = num_tables_new * 16;
334 for (i = 0; v; i++) {
335 v >>= 1;
336 searchRange |= v;
337 entrySelector++;
338 }
339 searchRange -= searchRange >> 1;
340 rangeShift = num_tables_new * 16 - searchRange;
341
342 w->wlong(w, version);
343 w->wword(w, num_tables_new);
344 w->wword(w, searchRange);
345 w->wword(w, entrySelector);
346 w->wword(w, rangeShift);
347 for (i = 0; i < num_tables; i++) {
348 if (sfnts_need_copy_table(tables[i].tag)) {
349 w->wstring(w, tables[i].tag, 4);
350 w->wlong(w, tables[i].checkSum);
351 w->wlong(w, tables[i].offset_new + num_tables_new * 16);
352 w->wlong(w, tables[i].length);
353 }
354 }
355 for (i = 0; i < num_tables; i++) {
356 if (sfnts_need_copy_table(tables[i].tag)) {
357 int k = tables[i].length;
358
359 r->seek(r, tables[i].offset);
360 if (r->error)
361 return 0;
362 if (w->p - w->buf != tables[i].offset_new + num_tables_new * 16)
363 return 0; /* the algorithm consistency check */
364 sfnt_copy_table(r, w, tables[i].length);
365 for (; k & (alignment - 1); k++)
366 w->wbyte(w, 0);
367 }
368 }
369 return (size_new);
370 }
371
372 static ulong
true_type_size(ref * pdr)373 true_type_size(ref *pdr)
374 {
375 sfnts_reader r;
376
377 sfnts_reader_init(&r, pdr);
378 return (sfnts_copy_except_glyf(&r, 0));
379 }
380
381 static ushort
FAPI_FF_serialize_tt_font(gs_fapi_font * ff,void * buf,int buf_size)382 FAPI_FF_serialize_tt_font(gs_fapi_font *ff, void *buf, int buf_size)
383 {
384 ref *pdr = pfont_dict(((gs_font_base *) ff->client_font_data2));
385 sfnts_reader r;
386 sfnts_writer w = sfnts_writer_stub;
387
388 w.buf_size = buf_size;
389 w.buf = w.p = buf;
390 sfnts_reader_init(&r, pdr);
391 if (!sfnts_copy_except_glyf(&r, &w))
392 return (1);
393 return (r.error);
394 }
395
396 static inline ushort
float_to_ushort(float v)397 float_to_ushort(float v)
398 {
399 return ((ushort) (v * 16)); /* fixme : the scale may depend on renderer */
400 }
401
402 /* In general, we assumed that the entries we use below have been validated (at least for type)
403 * at definefont time. This means validating each entry only once, rather than on every read
404 * here. Better, for example, for BlendDesignMap which is an array, of arrays, of arrays of
405 * numbers.
406 */
407 static ushort
FAPI_FF_get_word(gs_fapi_font * ff,gs_fapi_font_feature var_id,int index)408 FAPI_FF_get_word(gs_fapi_font *ff, gs_fapi_font_feature var_id, int index)
409 {
410 gs_font_type1 *pfont = (gs_font_type1 *) ff->client_font_data;
411 ref *pdr = pfont_dict(((gs_font_base *) ff->client_font_data2));
412
413 switch ((int)var_id) {
414 case gs_fapi_font_feature_Weight:
415 return 0; /* wrong */
416 case gs_fapi_font_feature_ItalicAngle:
417 return 0; /* wrong */
418 case gs_fapi_font_feature_IsFixedPitch:
419 return 0; /* wrong */
420 case gs_fapi_font_feature_UnderLinePosition:
421 return 0; /* wrong */
422 case gs_fapi_font_feature_UnderlineThickness:
423 return 0; /* wrong */
424 case gs_fapi_font_feature_FontType:
425 return (pfont->FontType == 2 ? 2 : 1);
426 case gs_fapi_font_feature_FontBBox:
427 switch (index) {
428 case 0:
429 return ((ushort) pfont->FontBBox.p.x);
430 case 1:
431 return ((ushort) pfont->FontBBox.p.y);
432 case 2:
433 return ((ushort) pfont->FontBBox.q.x);
434 case 3:
435 return ((ushort) pfont->FontBBox.q.y);
436 }
437 return 0;
438 case gs_fapi_font_feature_BlueValues_count:
439 return (pfont->data.BlueValues.count);
440 case gs_fapi_font_feature_BlueValues:
441 return (float_to_ushort(pfont->data.BlueValues.values[index]));
442 case gs_fapi_font_feature_OtherBlues_count:
443 return (pfont->data.OtherBlues.count);
444 case gs_fapi_font_feature_OtherBlues:
445 return (float_to_ushort(pfont->data.OtherBlues.values[index]));
446 case gs_fapi_font_feature_FamilyBlues_count:
447 return (pfont->data.FamilyBlues.count);
448 case gs_fapi_font_feature_FamilyBlues:
449 return (float_to_ushort(pfont->data.FamilyBlues.values[index]));
450 case gs_fapi_font_feature_FamilyOtherBlues_count:
451 return (pfont->data.FamilyOtherBlues.count);
452 case gs_fapi_font_feature_FamilyOtherBlues:
453 return (float_to_ushort
454 (pfont->data.FamilyOtherBlues.values[index]));
455 case gs_fapi_font_feature_BlueShift:
456 return (float_to_ushort(pfont->data.BlueShift));
457 case gs_fapi_font_feature_BlueFuzz:
458 return (float_to_ushort(pfont->data.BlueShift));
459 case gs_fapi_font_feature_StdHW:
460 return (pfont->data.StdHW.count == 0 ? 0 : float_to_ushort(pfont->data.StdHW.values[0])); /* UFST bug ? */
461 case gs_fapi_font_feature_StdVW:
462 return (pfont->data.StdVW.count == 0 ? 0 : float_to_ushort(pfont->data.StdVW.values[0])); /* UFST bug ? */
463 case gs_fapi_font_feature_StemSnapH_count:
464 return (pfont->data.StemSnapH.count);
465 case gs_fapi_font_feature_StemSnapH:
466 return (float_to_ushort(pfont->data.StemSnapH.values[index]));
467 case gs_fapi_font_feature_StemSnapV_count:
468 return (pfont->data.StemSnapV.count);
469 case gs_fapi_font_feature_StemSnapV:
470 return (float_to_ushort(pfont->data.StemSnapV.values[index]));
471 case gs_fapi_font_feature_ForceBold:
472 return (pfont->data.ForceBold);
473 case gs_fapi_font_feature_LanguageGroup:
474 return (pfont->data.LanguageGroup);
475 case gs_fapi_font_feature_lenIV:
476 return (ff->need_decrypt ? 0 : pfont->data.lenIV);
477 case gs_fapi_font_feature_GlobalSubrs_count:
478 {
479 ref *Private, *GlobalSubrs;
480
481 if (pfont->FontType == ft_encrypted2) {
482 if (dict_find_string(pdr, "Private", &Private) <= 0)
483 return 0;
484 if (dict_find_string(Private, "GlobalSubrs", &GlobalSubrs)
485 <= 0)
486 return 0;;
487 return (r_size(GlobalSubrs));
488 }
489 /* Since we don't have an error return capability, use as unlikely a value as possible */
490 return (65535);
491 }
492 case gs_fapi_font_feature_Subrs_count:
493 {
494 ref *Private, *Subrs;
495
496 if (dict_find_string(pdr, "Private", &Private) <= 0)
497 return 0;
498 if (dict_find_string(Private, "Subrs", &Subrs) <= 0)
499 return 0;
500 return (r_size(Subrs));
501 }
502 case gs_fapi_font_feature_CharStrings_count:
503 {
504 ref *CharStrings;
505
506 if (dict_find_string(pdr, "CharStrings", &CharStrings) <= 0)
507 return 0;
508 return (dict_maxlength(CharStrings));
509 }
510 /* Multiple Master specific */
511 case gs_fapi_font_feature_DollarBlend:
512 {
513 ref *DBlend;
514
515 if (dict_find_string(pdr, "$Blend", &DBlend) <= 0)
516 return 0;
517 return 1;
518 }
519 case gs_fapi_font_feature_BlendAxisTypes_count:
520 {
521 ref *Info, *Axes;
522
523 if (dict_find_string(pdr, "FontInfo", &Info) <= 0)
524 return 0;
525 if (dict_find_string(Info, "BlendAxisTypes", &Axes) <= 0)
526 return 0;
527 return (r_size(Axes));
528 }
529 case gs_fapi_font_feature_BlendFontInfo_count:
530 {
531 ref *Info, *FontInfo;
532
533 if (dict_find_string(pdr, "Blend", &Info) <= 0)
534 return 0;
535 if (dict_find_string(Info, "FontInfo", &FontInfo) <= 0)
536 return 0;
537 return (dict_length(FontInfo));
538 }
539 case gs_fapi_font_feature_BlendPrivate_count:
540 {
541 ref *Info, *Private;
542
543 if (dict_find_string(pdr, "Blend", &Info) <= 0)
544 return 0;
545 if (dict_find_string(Info, "Private", &Private) <= 0)
546 return 0;
547 return (dict_length(Private));
548 }
549 case gs_fapi_font_feature_WeightVector_count:
550 {
551 return pfont->data.WeightVector.count;
552 }
553 case gs_fapi_font_feature_BlendDesignPositionsArrays_count:
554 {
555 ref *Info, *Array;
556
557 if (dict_find_string(pdr, "FontInfo", &Info) <= 0)
558 return 0;
559 if (dict_find_string(Info, "BlendDesignPositions", &Array) <=
560 0)
561 return 0;
562 return (r_size(Array));
563 }
564 case gs_fapi_font_feature_BlendDesignMapArrays_count:
565 {
566 ref *Info, *Array;
567
568 if (dict_find_string(pdr, "FontInfo", &Info) <= 0)
569 return 0;
570 if (dict_find_string(Info, "BlendDesignMap", &Array) <= 0)
571 return 0;
572 return (r_size(Array));
573 }
574 case gs_fapi_font_feature_BlendDesignMapSubArrays_count:
575 {
576 ref *Info, *Array, SubArray;
577
578 if (dict_find_string(pdr, "FontInfo", &Info) <= 0)
579 return 0;
580 if (dict_find_string(Info, "BlendDesignMap", &Array) <= 0)
581 return 0;
582 if (array_get(ff->memory, Array, index, &SubArray) < 0)
583 return 0;
584 return (r_size(&SubArray));
585 }
586 case gs_fapi_font_feature_DollarBlend_length:
587 {
588 ref *DBlend, Element, string;
589 int i, length = 0;
590 char Buffer[32];
591
592 if (dict_find_string(pdr, "$Blend", &DBlend) <= 0)
593 return 0;
594 for (i = 0; i < r_size(DBlend); i++) {
595 if (array_get(ff->memory, DBlend, i, &Element) < 0)
596 return 0;
597 switch (r_btype(&Element)) {
598 case t_name:
599 name_string_ref(ff->memory, &Element, &string);
600 length += r_size(&string) + 1;
601 break;
602 case t_real:
603 gs_sprintf(Buffer, "%f", Element.value.realval);
604 length += strlen(Buffer) + 1;
605 break;
606 case t_integer:
607 gs_sprintf(Buffer, "%"PRIpsint, Element.value.intval);
608 length += strlen(Buffer) + 1;
609 break;
610 case t_operator:
611 {
612 op_def const *op;
613
614 op = op_index_def(r_size(&Element));
615 length += strlen(op->oname + 1) + 1;
616 }
617 break;
618 default:
619 break;
620 }
621 }
622 return length;
623 }
624 case gs_fapi_font_feature_BlendFontBBox_length:
625 {
626 ref *Blend, *bfbbox;
627 if (dict_find_string(pdr, "Blend", &Blend) <= 0)
628 return 0;
629
630 if (dict_find_string(Blend, "FontBBox", &bfbbox) <= 0)
631 return 0;
632 return ((ushort)r_size(bfbbox));
633 }
634 case gs_fapi_font_feature_BlendFontBBox:
635 {
636 ref *Blend, *bfbbox, subbfbbox, val;
637 int aind, ind;
638 if (dict_find_string(pdr, "Blend", &Blend) <= 0)
639 return 0;
640 if (dict_find_string(Blend, "FontBBox", &bfbbox) <= 0)
641 return 0;
642 ind = index % 4;
643 aind = (index - ind) /4;
644 if (array_get(ff->memory, bfbbox, aind, &subbfbbox) < 0)
645 return 0;
646 if (array_get(ff->memory, &subbfbbox, ind, &val) < 0)
647 return 0;
648
649 return (ushort)val.value.intval;
650 }
651 case gs_fapi_font_feature_BlendBlueValues_length:
652 {
653 ref *Priv, *Blend, *bbv;
654 if (dict_find_string(pdr, "Blend", &Blend) <= 0)
655 return 0;
656 if (dict_find_string(Blend, "Private", &Priv) <= 0)
657 return 0;
658 if (dict_find_string(Priv, "BlueValues", &bbv) <= 0)
659 return 0;
660 return ((ushort)r_size(bbv));
661 }
662 case gs_fapi_font_feature_BlendBlueValues_count:
663 {
664 ref *Priv, *Blend, *bbv, sub;
665
666 if (dict_find_string(pdr, "Blend", &Blend) <= 0)
667 return 0;
668 if (dict_find_string(Blend, "Private", &Priv) <= 0)
669 return 0;
670 if (dict_find_string(Priv, "BlueValues", &bbv) <= 0)
671 return 0;
672 if (array_get(ff->memory, bbv, index, &sub) < 0)
673 return 0;
674 return ((ushort)r_size(&sub));
675 }
676 case gs_fapi_font_feature_BlendBlueValues:
677 {
678 ref *Priv, *Blend, *bbv, sub, r;
679 int aind = 0;
680 if (dict_find_string(pdr, "Blend", &Blend) <= 0)
681 return 0;
682 if (dict_find_string(Blend, "Private", &Priv) <= 0)
683 return 0;
684 if (dict_find_string(Priv, "BlueValues", &bbv) <= 0)
685 return 0;
686
687 while (1) {
688 if (array_get(ff->memory, bbv, aind++, &sub) < 0)
689 return 0;
690 if (index - (int)r_size(&sub) < 0) {
691 break;
692 }
693 index -= r_size(&sub);
694 }
695 if (array_get(ff->memory, &sub, index, &r) < 0)
696 return 0;
697
698 return ((ushort)r.value.intval);
699 }
700 case gs_fapi_font_feature_BlendOtherBlues_length:
701 {
702 ref *Priv, *Blend, *bob;
703 if (dict_find_string(pdr, "Blend", &Blend) <= 0)
704 return 0;
705 if (dict_find_string(Blend, "Private", &Priv) <= 0)
706 return 0;
707 if (dict_find_string(Priv, "OtherBlues", &bob) <= 0)
708 return 0;
709 return ((ushort)r_size(bob));
710 }
711 case gs_fapi_font_feature_BlendOtherBlues_count:
712 {
713 ref *Priv, *Blend, *bob, sub;
714 if (dict_find_string(pdr, "Blend", &Blend) <= 0)
715 return 0;
716 if (dict_find_string(Blend, "Private", &Priv) <= 0)
717 return 0;
718 if (dict_find_string(Priv, "OtherBlues", &bob) <= 0)
719 return 0;
720
721 if (array_get(ff->memory, bob, index, &sub) < 0)
722 return 0;
723 return ((ushort)r_size(&sub));
724 }
725 case gs_fapi_font_feature_BlendOtherBlues:
726 {
727 ref *Priv, *Blend, *bob, sub, r;
728 int aind = 0;
729 if (dict_find_string(pdr, "Blend", &Blend) <= 0)
730 return 0;
731 if (dict_find_string(Blend, "Private", &Priv) <= 0)
732 return 0;
733 if (dict_find_string(Priv, "OtherBlues", &bob) <= 0)
734 return 0;
735
736 while (1) {
737 if (array_get(ff->memory, bob, aind++, &sub) < 0)
738 return 0;
739 if (index - (int)r_size(&sub) < 0) {
740 break;
741 }
742 index -= r_size(&sub);
743 }
744 if (array_get(ff->memory, &sub, index, &r) < 0)
745 return 0;
746
747 return ((ushort)r.value.intval);
748 }
749 case gs_fapi_font_feature_BlendBlueScale_count:
750 {
751 ref *Priv, *Blend, *bbs;
752 if (dict_find_string(pdr, "Blend", &Blend) <= 0)
753 return 0;
754 if (dict_find_string(Blend, "Private", &Priv) <= 0)
755 return 0;
756 if (dict_find_string(Priv, "BlueScale", &bbs) <= 0)
757 return 0;
758 return ((ushort)r_size(bbs));
759 }
760 case gs_fapi_font_feature_BlendBlueShift_count:
761 {
762 ref *Priv, *Blend, *bbs;
763 if (dict_find_string(pdr, "Blend", &Blend) <= 0)
764 return 0;
765 if (dict_find_string(Blend, "Private", &Priv) <= 0)
766 return 0;
767 if (dict_find_string(Priv, "BlueShift", &bbs) <= 0)
768 return 0;
769 return ((ushort)r_size(bbs));
770 }
771 case gs_fapi_font_feature_BlendBlueShift:
772 {
773 ref *Priv, *Blend, *bbs, r;
774 if (dict_find_string(pdr, "Blend", &Blend) <= 0)
775 return 0;
776 if (dict_find_string(Blend, "Private", &Priv) <= 0)
777 return 0;
778 if (dict_find_string(Priv, "BlueShift", &bbs) <= 0)
779 return 0;
780 if (array_get(ff->memory, bbs, index, &r) < 0)
781 return 0;
782
783 return ((ushort)r.value.intval);
784 }
785 case gs_fapi_font_feature_BlendBlueFuzz_count:
786 {
787 ref *Priv, *Blend, *bbf;
788 if (dict_find_string(pdr, "Blend", &Blend) <= 0)
789 return 0;
790 if (dict_find_string(Blend, "Private", &Priv) <= 0)
791 return 0;
792 if (dict_find_string(Priv, "BlueFuzz", &bbf) <= 0)
793 return 0;
794 return ((ushort)r_size(bbf));
795 }
796 case gs_fapi_font_feature_BlendBlueFuzz:
797 {
798 ref *Priv, *Blend, *bbf, r;
799 if (dict_find_string(pdr, "Blend", &Blend) <= 0)
800 return 0;
801 if (dict_find_string(Blend, "Private", &Priv) <= 0)
802 return 0;
803 if (dict_find_string(Priv, "BlueFuzz", &bbf) <= 0)
804 return 0;
805 if (array_get(ff->memory, bbf, index, &r) < 0)
806 return 0;
807
808 return ((ushort)r.value.intval);
809 }
810 case gs_fapi_font_feature_BlendForceBold_count:
811 {
812 ref *Priv, *Blend, *bfb;
813 if (dict_find_string(pdr, "Blend", &Blend) <= 0)
814 return 0;
815 if (dict_find_string(Blend, "Private", &Priv) <= 0)
816 return 0;
817 if (dict_find_string(Priv, "ForceBold", &bfb) <= 0)
818 return 0;
819 return ((ushort)r_size(bfb));
820 }
821 case gs_fapi_font_feature_BlendForceBold:
822 {
823 ref *Priv, *Blend, *bfb, r;
824 if (dict_find_string(pdr, "Blend", &Blend) <= 0)
825 return 0;
826 if (dict_find_string(Blend, "Private", &Priv) <= 0)
827 return 0;
828 if (dict_find_string(Priv, "BlueFuzz", &bfb) <= 0)
829 return 0;
830 if (array_get(ff->memory, bfb, index, &r) < 0)
831 return 0;
832
833 return ((ushort)r.value.boolval);
834 }
835 case gs_fapi_font_feature_BlendStdHW_length:
836 {
837 ref *Priv, *Blend, *stdhw;
838 if (dict_find_string(pdr, "Blend", &Blend) <= 0)
839 return 0;
840 if (dict_find_string(Blend, "Private", &Priv) <= 0)
841 return 0;
842 if (dict_find_string(Priv, "StdHW", &stdhw) <= 0)
843 return 0;
844 return ((ushort)r_size(stdhw));
845 }
846 case gs_fapi_font_feature_BlendStdHW_count:
847 {
848 ref *Priv, *Blend, *stdhw, sub;
849 if (dict_find_string(pdr, "Blend", &Blend) <= 0)
850 return 0;
851 if (dict_find_string(Blend, "Private", &Priv) <= 0)
852 return 0;
853 if (dict_find_string(Priv, "StdHW", &stdhw) <= 0)
854 return 0;
855
856 if (array_get(ff->memory, stdhw, index, &sub) < 0)
857 return 0;
858 return ((ushort)r_size(&sub));
859 }
860 case gs_fapi_font_feature_BlendStdHW:
861 {
862 ref *Priv, *Blend, *stdhw, sub, r;
863 int aind = 0;
864 if (dict_find_string(pdr, "Blend", &Blend) <= 0)
865 return 0;
866 if (dict_find_string(Blend, "Private", &Priv) <= 0)
867 return 0;
868 if (dict_find_string(Priv, "StdHW", &stdhw) <= 0)
869 return 0;
870
871 while (1) {
872 if (array_get(ff->memory, stdhw, aind++, &sub) < 0)
873 return 0;
874 if (index - (int)r_size(&sub) < 0) {
875 break;
876 }
877 index -= r_size(&sub);
878 }
879 if (array_get(ff->memory, &sub, index, &r) < 0)
880 return 0;
881
882 return ((ushort)r.value.intval);
883 }
884 case gs_fapi_font_feature_BlendStdVW_length:
885 {
886 ref *Priv, *Blend, *stdvw;
887 if (dict_find_string(pdr, "Blend", &Blend) <= 0)
888 return 0;
889 if (dict_find_string(Blend, "Private", &Priv) <= 0)
890 return 0;
891 if (dict_find_string(Priv, "StdVW", &stdvw) <= 0)
892 return 0;
893 return ((ushort)r_size(stdvw));
894 }
895 case gs_fapi_font_feature_BlendStdVW_count:
896 {
897 ref *Priv, *Blend, *stdvw, sub;
898 if (dict_find_string(pdr, "Blend", &Blend) <= 0)
899 return 0;
900 if (dict_find_string(Blend, "Private", &Priv) <= 0)
901 return 0;
902 if (dict_find_string(Priv, "StdVW", &stdvw) <= 0)
903 return 0;
904
905 if (array_get(ff->memory, stdvw, index, &sub) < 0)
906 return 0;
907 return ((ushort)r_size(&sub));
908 }
909 case gs_fapi_font_feature_BlendStdVW:
910 {
911 ref *Priv, *Blend, *stdvw, sub, r;
912 int aind = 0;
913 if (dict_find_string(pdr, "Blend", &Blend) <= 0)
914 return 0;
915 if (dict_find_string(Blend, "Private", &Priv) <= 0)
916 return 0;
917 if (dict_find_string(Priv, "StdVW", &stdvw) <= 0)
918 return 0;
919
920 while (1) {
921 if (array_get(ff->memory, stdvw, aind++, &sub) < 0)
922 return 0;
923 if (index - (int)r_size(&sub) < 0) {
924 break;
925 }
926 index -= r_size(&sub);
927 }
928 if (array_get(ff->memory, &sub, index, &r) < 0)
929 return 0;
930
931 return ((ushort)r.value.intval);
932 }
933 case gs_fapi_font_feature_BlendStemSnapH_length:
934 {
935 ref *Priv, *Blend, *ssh;
936 if (dict_find_string(pdr, "Blend", &Blend) <= 0)
937 return 0;
938 if (dict_find_string(Blend, "Private", &Priv) <= 0)
939 return 0;
940 if (dict_find_string(Priv, "StemSnapH", &ssh) <= 0)
941 return 0;
942 return ((ushort)r_size(ssh));
943 }
944 case gs_fapi_font_feature_BlendStemSnapH_count:
945 {
946 ref *Priv, *Blend, *bssh, sub;
947 if (dict_find_string(pdr, "Blend", &Blend) <= 0)
948 return 0;
949 if (dict_find_string(Blend, "Private", &Priv) <= 0)
950 return 0;
951 if (dict_find_string(Priv, "StemSnapH", &bssh) <= 0)
952 return 0;
953
954 if (array_get(ff->memory, bssh, index, &sub) < 0)
955 return 0;
956 return ((ushort)r_size(&sub));
957 }
958 case gs_fapi_font_feature_BlendStemSnapH:
959 {
960 ref *Priv, *Blend, *bssh, sub, r;
961 int aind = 0;
962 if (dict_find_string(pdr, "Blend", &Blend) <= 0)
963 return 0;
964 if (dict_find_string(Blend, "Private", &Priv) <= 0)
965 return 0;
966 if (dict_find_string(Priv, "StemSnapH", &bssh) <= 0)
967 return 0;
968
969 while (1) {
970 if (array_get(ff->memory, bssh, aind++, &sub) < 0)
971 return 0;
972 if (index - (int)r_size(&sub) < 0) {
973 break;
974 }
975 index -= r_size(&sub);
976 }
977 if (array_get(ff->memory, &sub, index, &r) < 0)
978 return 0;
979
980 return ((ushort)r.value.intval);
981 }
982 case gs_fapi_font_feature_BlendStemSnapV_length:
983 {
984 ref *Priv, *Blend, *ssv;
985 if (dict_find_string(pdr, "Blend", &Blend) <= 0)
986 return 0;
987 if (dict_find_string(Blend, "Private", &Priv) <= 0)
988 return 0;
989 if (dict_find_string(Priv, "StdHW", &ssv) <= 0)
990 return 0;
991 return ((ushort)r_size(ssv));
992 }
993 case gs_fapi_font_feature_BlendStemSnapV_count:
994 {
995 ref *Priv, *Blend, *bssv, sub;
996 if (dict_find_string(pdr, "Blend", &Blend) <= 0)
997 return 0;
998 if (dict_find_string(Blend, "Private", &Priv) <= 0)
999 return 0;
1000 if (dict_find_string(Priv, "StemSnapV", &bssv) <= 0)
1001 return 0;
1002
1003 if (array_get(ff->memory, bssv, index, &sub) < 0)
1004 return 0;
1005 return ((ushort)r_size(&sub));
1006 }
1007 case gs_fapi_font_feature_BlendStemSnapV:
1008 {
1009 ref *Priv, *Blend, *bssv, sub, r;
1010 int aind = 0;
1011 if (dict_find_string(pdr, "Blend", &Blend) <= 0)
1012 return 0;
1013 if (dict_find_string(Blend, "Private", &Priv) <= 0)
1014 return 0;
1015 if (dict_find_string(Priv, "StemSnapV", &bssv) <= 0)
1016 return 0;
1017
1018 while (1) {
1019 if (array_get(ff->memory, bssv, aind++, &sub) < 0)
1020 return 0;
1021 if (index - (int)r_size(&sub) < 0) {
1022 break;
1023 }
1024 index -= r_size(&sub);
1025 }
1026 if (array_get(ff->memory, &sub, index, &r) < 0)
1027 return 0;
1028
1029 return ((ushort)r.value.intval);
1030 }
1031
1032 /* End MM specifics */
1033 }
1034 return 0;
1035 }
1036
1037 static ulong
FAPI_FF_get_long(gs_fapi_font * ff,gs_fapi_font_feature var_id,int index)1038 FAPI_FF_get_long(gs_fapi_font *ff, gs_fapi_font_feature var_id, int index)
1039 {
1040 gs_font_type1 *pfont = (gs_font_type1 *) ff->client_font_data;
1041
1042 ref *pdr = pfont_dict(((gs_font_base *) ff->client_font_data2));
1043
1044 switch ((int)var_id) {
1045 case gs_fapi_font_feature_UniqueID:
1046 return (pfont->UID.id);
1047 case gs_fapi_font_feature_BlueScale:
1048 return ((ulong) (pfont->data.BlueScale * 65536));
1049 case gs_fapi_font_feature_Subrs_total_size:
1050 {
1051 ref *Private, *Subrs, v;
1052 int lenIV = max(pfont->data.lenIV, 0), k;
1053 ulong size = 0;
1054 long i;
1055 const char *name[2] = { "Subrs", "GlobalSubrs" };
1056 if (dict_find_string(pdr, "Private", &Private) <= 0)
1057 return 0;
1058 for (k = 0; k < 2; k++) {
1059 if (dict_find_string(Private, name[k], &Subrs) > 0)
1060 for (i = r_size(Subrs) - 1; i >= 0; i--) {
1061 array_get(pfont->memory, Subrs, i, &v);
1062 if (r_type(&v) == t_string) {
1063 size += r_size(&v) - (ff->need_decrypt ? 0 : lenIV);
1064 }
1065 }
1066 }
1067 return size;
1068 }
1069 case gs_fapi_font_feature_TT_size:
1070 return (true_type_size(pdr));
1071 }
1072 return 0;
1073 }
1074
1075 static float
FAPI_FF_get_float(gs_fapi_font * ff,gs_fapi_font_feature var_id,int index)1076 FAPI_FF_get_float(gs_fapi_font *ff, gs_fapi_font_feature var_id, int index)
1077 {
1078 gs_font_type1 *pfont1 = (gs_font_type1 *) ff->client_font_data;
1079 gs_font_base *pbfont = (gs_font_base *) ff->client_font_data2;
1080 ref *pdr = pfont_dict(pbfont);
1081
1082 gs_fapi_server *I = pbfont->FAPI;
1083
1084 switch ((int)var_id) {
1085 case gs_fapi_font_feature_FontMatrix:
1086 {
1087 double FontMatrix_div;
1088 gs_matrix m, *mptr;
1089
1090 if (I && I->get_fontmatrix) {
1091 FontMatrix_div = 1;
1092 mptr = &m;
1093 I->get_fontmatrix(I, mptr);
1094 }
1095 else {
1096 FontMatrix_div =
1097 ((ff->is_cid
1098 && (!FAPI_ISCIDFONT(pbfont))) ? 1000 : 1);
1099 mptr = &(pbfont->base->FontMatrix);
1100 }
1101 switch (index) {
1102 case 0:
1103 default:
1104 return (mptr->xx / FontMatrix_div);
1105 case 1:
1106 return (mptr->xy / FontMatrix_div);
1107 case 2:
1108 return (mptr->yx / FontMatrix_div);
1109 case 3:
1110 return (mptr->yy / FontMatrix_div);
1111 case 4:
1112 return (mptr->tx / FontMatrix_div);
1113 case 5:
1114 return (mptr->ty / FontMatrix_div);
1115 }
1116 }
1117
1118 case gs_fapi_font_feature_WeightVector:
1119 {
1120 if (index < pfont1->data.WeightVector.count) {
1121 return pfont1->data.WeightVector.values[index];
1122 }
1123 else {
1124 return 0;
1125 }
1126 }
1127 case gs_fapi_font_feature_BlendDesignPositionsArrayValue:
1128 {
1129 ref *Info, *Array, SubArray, value;
1130 int array_index = index / 8;
1131
1132 index %= 8;
1133 if (dict_find_string(pdr, "FontInfo", &Info) <= 0)
1134 return 0;
1135 if (dict_find_string(Info, "BlendDesignPositions", &Array) <=
1136 0)
1137 return 0;
1138 if (array_get(ff->memory, Array, array_index, &SubArray) < 0)
1139 return 0;
1140 if (array_get(ff->memory, &SubArray, index, &value) < 0)
1141 return 0;
1142 if (!r_has_type(&value, t_integer)) {
1143 if (r_has_type(&value, t_real)) {
1144 return (value.value.realval);
1145 }
1146 else
1147 return 0;
1148 }
1149 else
1150 return ((float)value.value.intval);
1151 }
1152 case gs_fapi_font_feature_BlendDesignMapArrayValue:
1153 {
1154 ref *Info, *Array, SubArray, SubSubArray, value;
1155 int array_index = index / 64;
1156
1157 index %= 8;
1158 if (dict_find_string(pdr, "FontInfo", &Info) <= 0)
1159 return 0;
1160 if (dict_find_string(Info, "BlendDesignMap", &Array) <= 0)
1161 return 0;
1162 if (array_get(ff->memory, Array, array_index, &SubArray) < 0)
1163 return 0;
1164 if (array_get(ff->memory, &SubArray, index, &SubSubArray) < 0)
1165 return 0;
1166 if (array_get(ff->memory, &SubSubArray, index, &value) < 0)
1167 return 0;
1168 if (!r_has_type(&value, t_integer)) {
1169 if (r_has_type(&value, t_real)) {
1170 return (value.value.realval);
1171 }
1172 else
1173 return 0;
1174 }
1175 else
1176 return ((float)value.value.intval);
1177 }
1178 case gs_fapi_font_feature_BlendBlueScale:
1179 {
1180 ref *Priv, *Blend, *bbs, r;
1181 float val = 0;
1182
1183 if (dict_find_string(pdr, "Blend", &Blend) <= 0)
1184 return 0;
1185 if (dict_find_string(Blend, "Private", &Priv) <= 0)
1186 return 0;
1187 if (dict_find_string(Priv, "BlueScale", &bbs) <= 0)
1188 return 0;
1189 if (array_get(ff->memory, bbs, index, &r) < 0)
1190 return 0;
1191 if (r_has_type(&r, t_real))
1192 val = r.value.realval;
1193 else if (r_has_type(&r, t_integer))
1194 val = (float)r.value.intval;
1195 return (val);
1196 }
1197 }
1198 return 0;
1199 }
1200
1201 static int
FAPI_FF_get_name(gs_fapi_font * ff,gs_fapi_font_feature var_id,int index,char * Buffer,int len)1202 FAPI_FF_get_name(gs_fapi_font *ff, gs_fapi_font_feature var_id, int index,
1203 char *Buffer, int len)
1204 {
1205 ref name, string;
1206 ref *pdr = pfont_dict(((gs_font_base *) ff->client_font_data2));
1207
1208 switch ((int)var_id) {
1209 case gs_fapi_font_feature_BlendAxisTypes:
1210 {
1211 ref *Info, *Axes;
1212
1213 if (dict_find_string(pdr, "FontInfo", &Info) <= 0)
1214 return 0;
1215 if (dict_find_string(Info, "BlendAxisTypes", &Axes) <= 0)
1216 return 0;
1217 if (!r_has_type(Axes, t_array))
1218 return 0;
1219 if (array_get(ff->memory, Axes, index, &name) < 0)
1220 return 0;
1221 }
1222 }
1223 name_string_ref(ff->memory, &name, &string);
1224 if (r_size(&string) >= len)
1225 return 0;
1226 memcpy(Buffer, string.value.const_bytes, r_size(&string));
1227 Buffer[r_size(&string)] = 0x00;
1228 return 1;
1229 }
1230
1231 /* NOTE: we checked the type of $Blend at definefont time, so we know it is a
1232 * procedure and don't need to check it again here
1233 */
1234 static int
FAPI_FF_get_proc(gs_fapi_font * ff,gs_fapi_font_feature var_id,int index,char * Buffer)1235 FAPI_FF_get_proc(gs_fapi_font *ff, gs_fapi_font_feature var_id, int index,
1236 char *Buffer)
1237 {
1238 ref *pdr = pfont_dict(((gs_font_base *) ff->client_font_data2));
1239 char *ptr = Buffer;
1240
1241 if (!Buffer)
1242 return 0;
1243
1244 switch ((int)var_id) {
1245 case gs_fapi_font_feature_DollarBlend:
1246 {
1247 ref *DBlend, Element, string;
1248 int i;
1249 char Buf[32];
1250
1251 if (dict_find_string(pdr, "$Blend", &DBlend) <= 0)
1252 return 0;
1253 for (i = 0; i < r_size(DBlend); i++) {
1254 *ptr++ = 0x20;
1255 if (array_get(ff->memory, DBlend, i, &Element) < 0)
1256 return 0;
1257 switch (r_btype(&Element)) {
1258 case t_name:
1259 name_string_ref(ff->memory, &Element, &string);
1260
1261 strncpy(ptr, (char *)string.value.const_bytes,
1262 r_size(&string));
1263 ptr += r_size(&string);
1264 break;
1265 case t_real:
1266 gs_sprintf(Buf, "%f", Element.value.realval);
1267 strcpy(ptr, Buf);
1268 ptr += strlen(Buf);
1269 break;
1270 case t_integer:
1271 gs_sprintf(Buf, "%"PRIpsint, Element.value.intval);
1272 strcpy(ptr, Buf);
1273 ptr += strlen(Buf);
1274 break;
1275 case t_operator:
1276 {
1277 op_def const *op;
1278
1279 op = op_index_def(r_size(&Element));
1280 strcpy(ptr, op->oname + 1);
1281 ptr += strlen(op->oname + 1);
1282 }
1283 break;
1284 default:
1285 break;
1286 }
1287 }
1288 }
1289 }
1290 return (ptr - Buffer);
1291 }
1292
1293 static inline void
decode_bytes(byte * p,const byte * s,int l,int lenIV)1294 decode_bytes(byte *p, const byte *s, int l, int lenIV)
1295 {
1296 ushort state = 4330;
1297
1298 for (; l; s++, l--) {
1299 uchar c = (*s ^ (state >> 8));
1300
1301 state = (*s + state) * crypt_c1 + crypt_c2;
1302 if (lenIV > 0)
1303 lenIV--;
1304 else {
1305 *p = c;
1306 p++;
1307 }
1308 }
1309 }
1310
1311 static ushort
get_type1_data(gs_fapi_font * ff,const ref * type1string,byte * buf,ushort buf_length)1312 get_type1_data(gs_fapi_font *ff, const ref *type1string,
1313 byte *buf, ushort buf_length)
1314 {
1315 gs_font_type1 *pfont = (gs_font_type1 *) ff->client_font_data;
1316 int lenIV = max(pfont->data.lenIV, 0);
1317 int length = r_size(type1string) - (ff->need_decrypt ? lenIV : 0);
1318
1319 if (buf != 0) {
1320 int l = min(length, buf_length); /*safety */
1321
1322 if (ff->need_decrypt && pfont->data.lenIV >= 0)
1323 decode_bytes(buf, type1string->value.const_bytes, l + lenIV,
1324 lenIV);
1325 else
1326 memcpy(buf, type1string->value.const_bytes, l);
1327 }
1328 return length;
1329 }
1330
1331 static ushort
FAPI_FF_get_gsubr(gs_fapi_font * ff,int index,byte * buf,ushort buf_length)1332 FAPI_FF_get_gsubr(gs_fapi_font *ff, int index, byte *buf, ushort buf_length)
1333 {
1334 ref *pdr = pfont_dict(((gs_font_base *) ff->client_font_data2));
1335 ref *Private, *GlobalSubrs, subr;
1336
1337 if (dict_find_string(pdr, "Private", &Private) <= 0)
1338 return 0;
1339 if (dict_find_string(Private, "GlobalSubrs", &GlobalSubrs) <= 0)
1340 return 0;
1341 if (array_get(ff->memory,
1342 GlobalSubrs, index, &subr) < 0 || r_type(&subr) != t_string)
1343 return 0;
1344 return (get_type1_data(ff, &subr, buf, buf_length));
1345 }
1346
1347 static ushort
FAPI_FF_get_subr(gs_fapi_font * ff,int index,byte * buf,ushort buf_length)1348 FAPI_FF_get_subr(gs_fapi_font *ff, int index, byte *buf, ushort buf_length)
1349 {
1350 ref *pdr = pfont_dict(((gs_font_base *) ff->client_font_data2));
1351 ref *Private, *Subrs, subr;
1352
1353 if (dict_find_string(pdr, "Private", &Private) <= 0)
1354 return 0;
1355 if (dict_find_string(Private, "Subrs", &Subrs) <= 0)
1356 return 0;
1357 if (array_get(ff->memory, Subrs, index, &subr) < 0
1358 || r_type(&subr) != t_string)
1359 return 0;
1360 return (get_type1_data(ff, &subr, buf, buf_length));
1361 }
1362
1363 static ushort
FAPI_FF_get_raw_subr(gs_fapi_font * ff,int index,byte * buf,ushort buf_length)1364 FAPI_FF_get_raw_subr(gs_fapi_font *ff, int index, byte *buf,
1365 ushort buf_length)
1366 {
1367 ref *pdr = pfont_dict(((gs_font_base *) ff->client_font_data2));
1368 ref *Private, *Subrs, subr;
1369
1370 if (dict_find_string(pdr, "Private", &Private) <= 0)
1371 return 0;
1372 if (dict_find_string(Private, "Subrs", &Subrs) <= 0)
1373 return 0;
1374 if (array_get(ff->memory, Subrs, index, &subr) < 0
1375 || r_type(&subr) != t_string)
1376 return 0;
1377 if (buf && buf_length && buf_length >= r_size(&subr)) {
1378 memcpy(buf, subr.value.const_bytes, r_size(&subr));
1379 }
1380 return (r_size(&subr));
1381 }
1382
1383 /* FAPI_FF_get_charstring_name() and FAPI_FF_get_charstring()
1384 *
1385 * Generally we'd want to use the dictionary content
1386 * enumeration API rather than dict_index_entry(), but
1387 * the FAPI interface doesn't enforce sequential accessing
1388 * of the indices.
1389 * Setting up enumeration and enumerating through the entries
1390 * until we reach the requested valid index is a performance
1391 * hit we don't want to pay.
1392 *
1393 * Luckily, the checks we need for invalid CharString contents
1394 * also handle empty "slots" in the dictionary.
1395 */
1396
1397 static ushort
FAPI_FF_get_charstring_name(gs_fapi_font * ff,int index,byte * buf,ushort buf_length)1398 FAPI_FF_get_charstring_name(gs_fapi_font *ff, int index, byte *buf,
1399 ushort buf_length)
1400 {
1401 ref *pdr = pfont_dict(((gs_font_base *) ff->client_font_data2));
1402 ref *CharStrings, eltp[2], string;
1403
1404 if (dict_find_string(pdr, "CharStrings", &CharStrings) <= 0)
1405 return 0;
1406 if (dict_index_entry(CharStrings, index, eltp) < 0)
1407 return 0;
1408 if (r_type(&eltp[0]) != t_name)
1409 return 0;
1410 name_string_ref(ff->memory, &eltp[0], &string);
1411 if (r_size(&string) > buf_length)
1412 return (r_size(&string));
1413 memcpy(buf, string.value.const_bytes, r_size(&string));
1414 buf[r_size(&string)] = 0x00;
1415 return (r_size(&string));
1416 }
1417
1418 static ushort
FAPI_FF_get_charstring(gs_fapi_font * ff,int index,byte * buf,ushort buf_length)1419 FAPI_FF_get_charstring(gs_fapi_font *ff, int index, byte *buf,
1420 ushort buf_length)
1421 {
1422 ref *pdr = pfont_dict(((gs_font_base *) ff->client_font_data2));
1423 ref *CharStrings, eltp[2];
1424
1425 if (dict_find_string(pdr, "CharStrings", &CharStrings) <= 0)
1426 return 0;
1427 if (dict_index_entry(CharStrings, index, eltp) < 0)
1428 return 0;
1429 if (r_type(&eltp[1]) != t_string)
1430 return 0;
1431 if (buf && buf_length && buf_length >= r_size(&eltp[1])) {
1432 memcpy(buf, eltp[1].value.const_bytes, r_size(&eltp[1]));
1433 }
1434 return (r_size(&eltp[1]));
1435 }
1436
1437 static int
sfnt_get_sfnt_length(ref * pdr,ulong * len)1438 sfnt_get_sfnt_length(ref *pdr, ulong *len)
1439 {
1440 int code = 0;
1441 ref *sfnts, sfnt_elem;
1442 const gs_memory_t *mem = dict_mem(pdr->value.pdict);
1443
1444 *len = 0;
1445 if (r_type(pdr) != t_dictionary ||
1446 dict_find_string(pdr, "sfnts", &sfnts) <= 0) {
1447 code = gs_error_invalidfont;
1448 }
1449 else {
1450 if (r_type(sfnts) != t_array && r_type(sfnts) != t_string) {
1451 code = gs_error_invalidfont;
1452 }
1453 else {
1454 if (r_type(sfnts) == t_string) {
1455 *len = r_size(sfnts);
1456 }
1457 else {
1458 int i;
1459 for (i = 0; i < r_size(sfnts); i++) {
1460 code = array_get(mem, sfnts, i, &sfnt_elem);
1461 if (code < 0) break;
1462 *len += r_size(&sfnt_elem);
1463 }
1464 }
1465 }
1466 }
1467 return code;
1468 }
1469
1470 static bool
sfnt_get_glyph_offset(ref * pdr,gs_font_type42 * pfont42,int index,ulong * offset0)1471 sfnt_get_glyph_offset(ref *pdr, gs_font_type42 *pfont42, int index,
1472 ulong *offset0)
1473 { /* Note : TTC is not supported and probably is unuseful for Type 42. */
1474 sfnts_reader r;
1475 int glyf_elem_size = (pfont42->data.indexToLocFormat) ? 4 : 2;
1476
1477 if (index < pfont42->data.trueNumGlyphs) {
1478 sfnts_reader_init(&r, pdr);
1479 r.seek(&r, pfont42->data.loca + index * glyf_elem_size);
1480 *offset0 =
1481 pfont42->data.glyf + (glyf_elem_size ==
1482 2 ? r.rword(&r) * 2 : r.rlong(&r));
1483 }
1484 else {
1485 r.error = true;
1486 }
1487 return (r.error);
1488 }
1489
1490 static int
ps_get_GlyphDirectory_data_ptr(gs_fapi_font * ff,int char_code,const byte ** ptr)1491 ps_get_GlyphDirectory_data_ptr(gs_fapi_font *ff, int char_code,
1492 const byte **ptr)
1493 {
1494 ref *pdr = pfont_dict(((gs_font_base *) ff->client_font_data2));
1495 ref *GlyphDirectory, glyph0, *glyph = &glyph0, glyph_index;
1496
1497 if (dict_find_string(pdr, "GlyphDirectory", &GlyphDirectory) > 0) {
1498 if (((r_type(GlyphDirectory) == t_dictionary &&
1499 (make_int(&glyph_index, char_code),
1500 dict_find(GlyphDirectory, &glyph_index, &glyph) > 0)) ||
1501 (r_type(GlyphDirectory) == t_array &&
1502 array_get(ff->memory, GlyphDirectory, char_code, &glyph0) >= 0)
1503 )
1504 && r_type(glyph) == t_string) {
1505 *ptr = glyph->value.const_bytes;
1506 return (r_size(glyph));
1507 }
1508 else
1509 /* We have a GlyphDirectory, but couldn't find the glyph. If we
1510 * return -1 then we will attempt to use glyf and loca which
1511 * will fail. Instead return 0, so we execute an 'empty' glyph.
1512 */
1513 return 0;
1514 }
1515 return -1;
1516 }
1517
1518 static int
get_charstring(gs_fapi_font * ff,int char_code,ref ** proc,ref * char_name)1519 get_charstring(gs_fapi_font *ff, int char_code, ref **proc, ref *char_name)
1520 {
1521 ref *CharStrings;
1522 ref *pdr = pfont_dict(((gs_font_base *) ff->client_font_data2));
1523
1524 if (ff->is_type1) {
1525 if (ff->is_cid)
1526 return -1;
1527 if (dict_find_string(pdr, "CharStrings", &CharStrings) <= 0)
1528 return -1;
1529
1530 if (ff->char_data != NULL) {
1531 /*
1532 * Can't use char_code in this case because hooked Type 1 fonts
1533 * with 'glyphshow' may render a character which has no
1534 * Encoding entry.
1535 */
1536 if (name_ref
1537 (ff->memory, ff->char_data, ff->char_data_len, char_name,
1538 -1) < 0)
1539 return -1;
1540 }
1541 else { /* seac */
1542 i_ctx_t *i_ctx_p = (i_ctx_t *) ff->client_ctx_p;
1543 ref *StandardEncoding;
1544
1545 if (dict_find_string
1546 (systemdict, "StandardEncoding", &StandardEncoding) <= 0
1547 || array_get(ff->memory, StandardEncoding, char_code,
1548 char_name) < 0) {
1549 if (name_ref
1550 (ff->memory, (const byte *)".notdef", 7, char_name,
1551 -1) < 0)
1552 return -1;
1553 }
1554 }
1555 if (dict_find(CharStrings, char_name, (ref **) proc) <= 0)
1556 return -1;
1557 }
1558 return 0;
1559 }
1560
1561 static int
FAPI_FF_get_glyph(gs_fapi_font * ff,int char_code,byte * buf,ushort buf_length)1562 FAPI_FF_get_glyph(gs_fapi_font *ff, int char_code, byte *buf,
1563 ushort buf_length)
1564 {
1565 /*
1566 * We assume that renderer requests glyph data with multiple
1567 * consecutive calls to this function.
1568 *
1569 * For a simple glyph it calls this function exactly twice: first
1570 * with buf == NULL for requesting the necessary buffer length, and
1571 * second with buf != NULL for requesting the data (the second call
1572 * may be skipped if the renderer discontinues the rendering).
1573 *
1574 * For a composite glyph it calls this function 2 * (N + 1)
1575 * times: 2 calls for the main glyph (same as above) followed with
1576 * 2 * N calls for subglyphs, where N is less or equal to the number
1577 * of subglyphs (N may be less if the renderer caches glyph data,
1578 * or discontinues rendering on an exception).
1579 */
1580 ref *pdr = pfont_dict(((gs_font_base *) ff->client_font_data2));
1581
1582 int glyph_length;
1583 i_ctx_t *i_ctx_p = (i_ctx_t *) ff->client_ctx_p;
1584
1585 if (ff->is_type1) {
1586 if (ff->is_cid) {
1587 const gs_string *char_str = (const gs_string *)ff->char_data;
1588 ref glyph;
1589
1590 make_string(&glyph, avm_foreign | a_readonly, char_str->size,
1591 char_str->data);
1592
1593 glyph_length = get_type1_data(ff, &glyph, buf, buf_length);
1594 }
1595 else {
1596 ref *CharStrings, char_name, *glyph;
1597
1598 if (ff->char_data != NULL) {
1599 /*
1600 * Can't use char_code in this case because hooked Type 1 fonts
1601 * with 'glyphshow' may render a character which has no
1602 * Encoding entry.
1603 */
1604 if (name_ref(ff->memory, ff->char_data,
1605 ff->char_data_len, &char_name, -1) < 0)
1606 return gs_fapi_glyph_invalid_format;
1607 if (buf != NULL) {
1608 /*
1609 * Trigger the next call to the 'seac' case below.
1610 * Here we use the assumption about call sequence
1611 * being documented above.
1612 */
1613 ff->char_data = NULL;
1614 }
1615 }
1616 else { /* seac */
1617 ref *StandardEncoding;
1618
1619 if (dict_find_string
1620 (systemdict, "StandardEncoding", &StandardEncoding) <= 0
1621 || array_get(ff->memory, StandardEncoding, char_code,
1622 &char_name) < 0)
1623 if (name_ref
1624 (ff->memory, (const byte *)".notdef", 7, &char_name,
1625 -1) < 0)
1626 return gs_fapi_glyph_invalid_format;
1627 }
1628 if (dict_find_string(pdr, "CharStrings", &CharStrings) <= 0)
1629 return gs_fapi_glyph_invalid_format;
1630
1631 if (dict_find(CharStrings, &char_name, &glyph) <= 0) {
1632 if (name_ref
1633 (ff->memory, (const byte *)".notdef", 7, &char_name,
1634 -1) < 0) {
1635 return gs_fapi_glyph_invalid_format;
1636 }
1637 if (dict_find(CharStrings, &char_name, &glyph) <= 0) {
1638 return gs_fapi_glyph_invalid_format;
1639 }
1640 }
1641 if (r_has_type(glyph, t_array) || r_has_type(glyph, t_mixedarray))
1642 return gs_fapi_glyph_invalid_format;
1643 if (!r_has_type(glyph, t_string))
1644 return 0;
1645 glyph_length = get_type1_data(ff, glyph, buf, buf_length);
1646 }
1647 }
1648 else { /* type 42 */
1649 const byte *data_ptr;
1650 int l = ff->get_glyphdirectory_data(ff, char_code, &data_ptr);
1651 ref *render_notdef_ref;
1652 bool render_notdef = true;
1653
1654 if (dict_find_string(pdr, ".render_notdef", &render_notdef_ref) > 0
1655 && r_has_type(render_notdef_ref, t_boolean)) {
1656 render_notdef = render_notdef_ref->value.boolval;
1657 }
1658 else {
1659 render_notdef = i_ctx_p->RenderTTNotdef;
1660 }
1661
1662 /* We should only render the TT notdef if we've been told to - logic lifted from zchar42.c */
1663 if (!render_notdef
1664 &&
1665 ((ff->char_data_len == 7
1666 && strncmp((const char *)ff->char_data, ".notdef", 7) == 0)
1667 || (ff->char_data_len > 9
1668 && strncmp((const char *)ff->char_data, ".notdef~GS",
1669 10) == 0))) {
1670 glyph_length = 0;
1671 }
1672 else {
1673 if (l >= 0) {
1674 int MetricsCount = gs_fapi_get_metrics_count(ff), mc =
1675 MetricsCount << 1;
1676
1677 glyph_length = max((ushort) (l - mc), 0); /* safety */
1678 if (buf != 0 && glyph_length > 0)
1679 memcpy(buf, data_ptr + mc,
1680 min(glyph_length, buf_length) /* safety */ );
1681 }
1682 else {
1683 gs_font_type42 *pfont42 = (gs_font_type42 *) ff->client_font_data;
1684 ulong offset0, length_read;
1685 bool error = sfnt_get_glyph_offset(pdr, pfont42, char_code, &offset0);
1686
1687 if (error != 0) {
1688 glyph_length = gs_fapi_glyph_invalid_index;
1689 }
1690 else if (pfont42->data.len_glyphs) {
1691 if (char_code <= pfont42->data.numGlyphs)
1692 glyph_length = pfont42->data.len_glyphs[char_code];
1693 else
1694 glyph_length = gs_fapi_glyph_invalid_index;
1695 }
1696 else {
1697 ulong noffs;
1698 /* If we haven't got a len_glyphs array, try using the offset of the next glyph offset
1699 * to work out the length
1700 */
1701 error = sfnt_get_glyph_offset(pdr, pfont42, char_code + 1, &noffs);
1702 if (error == 0) {
1703 glyph_length = noffs - offset0;
1704 }
1705 else {
1706 /* And if we can't get the next glyph offset, use the end of the sfnt data
1707 * to work out the length.
1708 */
1709 int code = sfnt_get_sfnt_length(pdr, &noffs);
1710 if (code < 0) {
1711 glyph_length = gs_fapi_glyph_invalid_index;
1712 }
1713 else {
1714 glyph_length = noffs - offset0;
1715 }
1716 }
1717 }
1718
1719 if (buf != 0 && !error) {
1720 sfnts_reader r;
1721
1722 sfnts_reader_init(&r, pdr);
1723
1724 r.seek(&r, offset0);
1725 length_read =
1726 r.rstring(&r, buf,
1727 min(glyph_length,
1728 buf_length) /* safety */ );
1729 if (r.error == 1) {
1730 glyph_length = gs_fapi_glyph_invalid_index;
1731 }
1732 /* r.error == 2 means a rangecheck, and probably means that the
1733 * font is broken, and the final glyph length is longer than the data available for it.
1734 * In which case we need to return the number of bytes read.
1735 */
1736 if (r.error == 2) {
1737 glyph_length = length_read;
1738 }
1739 }
1740 }
1741 }
1742 }
1743 return glyph_length;
1744 }
1745
1746 static int
ps_fapi_get_metrics(gs_fapi_font * ff,gs_string * char_name,int cid,double * m,bool vertical)1747 ps_fapi_get_metrics(gs_fapi_font *ff, gs_string *char_name, int cid,
1748 double *m, bool vertical)
1749 {
1750 ref glyph;
1751 int code;
1752 gs_font_base *pbfont = ((gs_font_base *) ff->client_font_data2);
1753
1754 if (char_name->data != NULL) {
1755 make_string(&glyph, avm_foreign | a_readonly, char_name->size,
1756 char_name->data);
1757 }
1758 else {
1759 make_int(&glyph, cid);
1760 }
1761
1762 if (vertical) {
1763 code = zchar_get_metrics2(pbfont, &glyph, m);
1764 }
1765 else {
1766 code = zchar_get_metrics(pbfont, &glyph, m);
1767 }
1768
1769 make_null(&glyph);
1770
1771 return (code);
1772 }
1773
1774
1775 /* forward declaration for the ps_ff_stub assignment */
1776 static int ps_get_glyphname_or_cid(gs_text_enum_t *penum,
1777 gs_font_base *pbfont,
1778 gs_string *charstring, gs_string *name,
1779 int ccode, gs_string *enc_char_name,
1780 char *font_file_path,
1781 gs_fapi_char_ref *cr, bool bCID);
1782
1783 static int ps_fapi_set_cache(gs_text_enum_t *penum,
1784 const gs_font_base *pbfont,
1785 const gs_string *char_name, int cid,
1786 const double pwidth[2], const gs_rect *pbbox,
1787 const double Metrics2_sbw_default[4],
1788 bool *imagenow);
1789
1790 static const gs_fapi_font ps_ff_stub = {
1791 0, /* server_font_data */
1792 0, /* need_decrypt */
1793 NULL, /* const gs_memory_t */
1794 0, /* font_file_path */
1795 0, /* full_font_buf */
1796 0, /* full_font_buf_len */
1797 0, /* subfont */
1798 false, /* is_type1 */
1799 false, /* is_cid */
1800 false, /* is_outline_font */
1801 false, /* is_mtx_skipped */
1802 false, /* is_vertical */
1803 false, /* metrics_only */
1804 {{-1, -1}}, /* ttf_cmap_req */
1805 {-1, -1}, /* ttf_cmap_selected */
1806 0, /* client_ctx_p */
1807 0, /* client_font_data */
1808 0, /* client_font_data2 */
1809 0, /* char_data */
1810 0, /* char_data_len */
1811 0, /* embolden */
1812 FAPI_FF_get_word,
1813 FAPI_FF_get_long,
1814 FAPI_FF_get_float,
1815 FAPI_FF_get_name,
1816 FAPI_FF_get_proc,
1817 FAPI_FF_get_gsubr,
1818 FAPI_FF_get_subr,
1819 FAPI_FF_get_raw_subr,
1820 FAPI_FF_get_glyph,
1821 FAPI_FF_serialize_tt_font,
1822 FAPI_FF_get_charstring,
1823 FAPI_FF_get_charstring_name,
1824 ps_get_GlyphDirectory_data_ptr,
1825 ps_get_glyphname_or_cid,
1826 ps_fapi_get_metrics,
1827 ps_fapi_set_cache
1828 };
1829
1830 static int
FAPI_get_xlatmap(i_ctx_t * i_ctx_p,char ** xlatmap)1831 FAPI_get_xlatmap(i_ctx_t *i_ctx_p, char **xlatmap)
1832 {
1833 ref *pref;
1834 int code;
1835
1836 if ((code = dict_find_string(systemdict, ".xlatmap", &pref)) < 0)
1837 return code;
1838 if (code == 0)
1839 return_error(gs_error_undefined);
1840
1841 if (r_type(pref) != t_string)
1842 return_error(gs_error_typecheck);
1843 *xlatmap = (char *)pref->value.bytes;
1844 /* Note : this supposes that xlatmap doesn't move in virtual memory.
1845 Garbager must not be called while plugin executes get_scaled_font, get_decodingID.
1846 Fix some day with making copy of xlatmap in system memory.
1847 */
1848 return 0;
1849 }
1850
1851 static int
renderer_retcode(gs_memory_t * mem,gs_fapi_server * I,gs_fapi_retcode rc)1852 renderer_retcode(gs_memory_t *mem, gs_fapi_server *I, gs_fapi_retcode rc)
1853 {
1854 if (rc == 0)
1855 return 0;
1856 emprintf2(mem,
1857 "Error: Font Renderer Plugin ( %s ) return code = %d\n",
1858 I->ig.d->subtype, rc);
1859 return rc < 0 ? rc : gs_error_invalidfont;
1860 }
1861
1862 /* <server name>/<null> object .FAPIavailable bool */
1863 static int
zFAPIavailable(i_ctx_t * i_ctx_p)1864 zFAPIavailable(i_ctx_t *i_ctx_p)
1865 {
1866 os_ptr op = osp;
1867 char *serv_name = NULL;
1868 ref name_ref;
1869
1870 check_op(1);
1871 if (r_has_type(op, t_name)) {
1872 name_string_ref(imemory, op, &name_ref);
1873
1874 serv_name =
1875 (char *) ref_to_string(&name_ref, imemory, "zFAPIavailable");
1876 if (!serv_name) {
1877 return_error(gs_error_VMerror);
1878 }
1879 }
1880
1881 make_bool(op, gs_fapi_available(imemory, serv_name));
1882
1883 if (serv_name) {
1884 gs_free_string(imemory, (byte *) serv_name,
1885 strlen((char *)serv_name) + 1, "zFAPIavailable");
1886 }
1887 return (0);
1888 }
1889
1890 static void
ps_get_server_param(gs_fapi_server * I,const byte * subtype,byte ** server_param,int * server_param_size)1891 ps_get_server_param(gs_fapi_server *I, const byte *subtype,
1892 byte **server_param, int *server_param_size)
1893 {
1894 ref *FAPIconfig, *options, *server_options;
1895 i_ctx_t *i_ctx_p = (i_ctx_t *) I->client_ctx_p;
1896
1897 if (dict_find_string(systemdict, ".FAPIconfig", &FAPIconfig) > 0
1898 && r_has_type(FAPIconfig, t_dictionary)) {
1899 if (dict_find_string(FAPIconfig, "ServerOptions", &options) > 0
1900 && r_has_type(options, t_dictionary)) {
1901 if (dict_find_string(options, (char *)subtype, &server_options) >
1902 0 && r_has_type(server_options, t_string)) {
1903 *server_param = (byte *) server_options->value.const_bytes;
1904 *server_param_size = r_size(server_options);
1905 }
1906 }
1907 }
1908 }
1909
1910 static int
FAPI_refine_font(i_ctx_t * i_ctx_p,os_ptr op,gs_font * pfont,int subfont,const char * font_file_path)1911 FAPI_refine_font(i_ctx_t *i_ctx_p, os_ptr op, gs_font *pfont,
1912 int subfont, const char *font_file_path)
1913 {
1914 ref *pdr = op; /* font dict */
1915 const char *decodingID = NULL;
1916 char *xlatmap = NULL;
1917 gs_font_base *pbfont = (gs_font_base *)pfont;
1918 gs_fapi_server *I = pbfont->FAPI;
1919 ref *Decoding_old;
1920 int code;
1921
1922 if (font_file_path != NULL && pbfont->FAPI_font_data == NULL)
1923 if ((code = FAPI_get_xlatmap(i_ctx_p, &xlatmap)) < 0)
1924 return code;
1925
1926 gs_fapi_set_servers_client_data(imemory, NULL, i_ctx_p);
1927
1928 code =
1929 gs_fapi_prepare_font(pfont, I, subfont, font_file_path,
1930 NULL, xlatmap, &decodingID);
1931 if (code < 0)
1932 return code;
1933
1934 if (code > 0) {
1935 /* save refined FontBBox back to PS world */
1936 ref *v, mat[4], arr;
1937 int attrs;
1938
1939 if (dict_find_string(op, "FontBBox", &v) > 0) {
1940 if (!r_has_type(v, t_array) && !r_has_type(v, t_shortarray)
1941 && !r_has_type(v, t_mixedarray))
1942 return_error(gs_error_invalidfont);
1943 make_real(&mat[0], pbfont->FontBBox.p.x);
1944 make_real(&mat[1], pbfont->FontBBox.p.y);
1945 make_real(&mat[2], pbfont->FontBBox.q.x);
1946 make_real(&mat[3], pbfont->FontBBox.q.y);
1947 if (r_has_type(v, t_shortarray) || r_has_type(v, t_mixedarray)
1948 || r_size(v) < 4) {
1949 /* Create a new full blown array in case the values are reals */
1950 code = ialloc_ref_array(&arr, a_all, 4, "array");
1951 if (code < 0)
1952 return code;
1953 v = &arr;
1954 code = idict_put_string(op, "FontBBox", &arr);
1955 if (code < 0)
1956 return code;
1957 ref_assign_new(v->value.refs + 0, &mat[0]);
1958 ref_assign_new(v->value.refs + 1, &mat[1]);
1959 ref_assign_new(v->value.refs + 2, &mat[2]);
1960 ref_assign_new(v->value.refs + 3, &mat[3]);
1961 }
1962 else {
1963 ref_assign_old(v, v->value.refs + 0, &mat[0],
1964 "FAPI_refine_font_BBox");
1965 ref_assign_old(v, v->value.refs + 1, &mat[1],
1966 "FAPI_refine_font_BBox");
1967 ref_assign_old(v, v->value.refs + 2, &mat[2],
1968 "FAPI_refine_font_BBox");
1969 ref_assign_old(v, v->value.refs + 3, &mat[3],
1970 "FAPI_refine_font_BBox");
1971 }
1972 attrs = v->tas.type_attrs;
1973 r_clear_attrs(v, a_all);
1974 r_set_attrs(v, attrs | a_execute);
1975 }
1976 }
1977
1978 /* Assign a Decoding : */
1979 if (decodingID != 0 && *decodingID
1980 && dict_find_string(pdr, "Decoding", &Decoding_old) <= 0) {
1981 ref Decoding;
1982
1983 if (FAPI_ISCIDFONT(pbfont)) {
1984 ref *CIDSystemInfo, *Ordering, SubstNWP;
1985 byte buf[30];
1986 int ordering_length, decodingID_length =
1987 min(strlen(decodingID), sizeof(buf) - 2);
1988
1989 if (dict_find_string(pdr, "CIDSystemInfo", &CIDSystemInfo) <= 0
1990 || !r_has_type(CIDSystemInfo, t_dictionary))
1991 return_error(gs_error_invalidfont);
1992
1993 if (dict_find_string(CIDSystemInfo, "Ordering", &Ordering) <= 0
1994 || !r_has_type(Ordering, t_string)) {
1995 return_error(gs_error_invalidfont);
1996 }
1997
1998 ordering_length =
1999 min(r_size(Ordering), sizeof(buf) - 2 - decodingID_length);
2000 memcpy(buf, Ordering->value.const_bytes, ordering_length);
2001 if ((code =
2002 name_ref(imemory, buf, ordering_length, &SubstNWP, 0)) < 0)
2003 return code;
2004 if ((code =
2005 dict_put_string(pdr, "SubstNWP", &SubstNWP, NULL)) < 0)
2006 return code;
2007 buf[ordering_length] = '.';
2008 memcpy(buf + ordering_length + 1, decodingID, decodingID_length);
2009 buf[decodingID_length + 1 + ordering_length] = 0; /* Debug purpose only */
2010 if ((code = name_ref(imemory, buf,
2011 decodingID_length + 1 + ordering_length,
2012 &Decoding, 0)) < 0)
2013 return code;
2014 }
2015 else if ((code = name_ref(imemory, (const byte *)decodingID,
2016 strlen(decodingID), &Decoding, 0)) < 0)
2017 return code;
2018 if ((code = dict_put_string(pdr, "Decoding", &Decoding, NULL)) < 0)
2019 return code;
2020 }
2021 return 0;
2022 }
2023
2024 /* <string|name> <font> <is_disk_font> .rebuildfontFAPI <string|name> <font> */
2025 /* Rebuild a font for handling it with an external renderer.
2026
2027 The font was built as a native GS font to allow easy access
2028 to font features. Then zFAPIrebuildfont sets FAPI entry
2029 into gx_font_base and replaces BuildGlyph and BuildChar
2030 to enforce the FAPI handling.
2031
2032 This operator must not be called with devices which embed fonts.
2033
2034 */
2035 static int
zFAPIrebuildfont(i_ctx_t * i_ctx_p)2036 zFAPIrebuildfont(i_ctx_t *i_ctx_p)
2037 {
2038 os_ptr op = osp;
2039 build_proc_refs build;
2040 gs_font *pfont;
2041 int code = font_param(op - 1, &pfont);
2042 gs_font_base *pbfont = (gs_font_base *) pfont;
2043 ref *v;
2044 char *font_file_path = NULL;
2045 char FAPI_ID[20];
2046 const byte *pchars;
2047 uint len;
2048 font_data *pdata;
2049 gs_fapi_server *I;
2050 bool has_buildglyph;
2051 bool has_buildchar;
2052 int subfont;
2053
2054 if (code < 0)
2055 return code;
2056
2057 check_type(*op, t_boolean);
2058 /* If someone has copied the font dictionary, we may still
2059 * have the FAPI entry in the dict, but not have the FAPI
2060 * server assigned in the font object.
2061 */
2062 if (pbfont->FAPI == NULL) {
2063 if (dict_find_string(op - 1, "FAPI", &v) <= 0
2064 || !r_has_type(v, t_name))
2065 return_error(gs_error_invalidfont);
2066 obj_string_data(imemory, v, &pchars, &len);
2067 len = min(len, sizeof(FAPI_ID) - 1);
2068 strncpy((char *)FAPI_ID, (const char *)pchars, len);
2069 FAPI_ID[len] = 0;
2070
2071 gs_fapi_set_servers_client_data(imemory, &ps_ff_stub, i_ctx_p);
2072
2073 code =
2074 gs_fapi_find_server(imemory, FAPI_ID,
2075 (gs_fapi_server **) & (pbfont->FAPI),
2076 (gs_fapi_get_server_param_callback)
2077 ps_get_server_param);
2078 if (!pbfont->FAPI || code < 0) {
2079 return_error(gs_error_invalidfont);
2080 }
2081 }
2082
2083 pdata = (font_data *) pfont->client_data;
2084 I = pbfont->FAPI;
2085
2086 if (dict_find_string((op - 1), "SubfontId", &v) > 0
2087 && r_has_type(v, t_integer))
2088 subfont = v->value.intval;
2089 else
2090 subfont = 0;
2091
2092
2093 if (r_type(&(pdata->BuildGlyph)) != t_null) {
2094 has_buildglyph = true;
2095 }
2096 else {
2097 has_buildglyph = false;
2098 }
2099
2100 if (r_type(&(pdata->BuildChar)) != t_null) {
2101 has_buildchar = true;
2102 }
2103 else {
2104 has_buildchar = false;
2105 }
2106
2107 /* This shouldn't happen, but just in case */
2108 if (has_buildglyph == false && has_buildchar == false) {
2109 has_buildglyph = true;
2110 }
2111
2112 if (dict_find_string(op - 1, "Path", &v) <= 0 || !r_has_type(v, t_string)) {
2113 v = NULL;
2114 }
2115
2116 if (pfont->FontType == ft_CID_encrypted && v == NULL) {
2117 if ((code = build_proc_name_refs(imemory, &build, ".FAPIBuildGlyph9",
2118 ".FAPIBuildGlyph9")) < 0) {
2119 return code;
2120 }
2121 }
2122 else {
2123 if ((code = build_proc_name_refs(imemory, &build, ".FAPIBuildChar",
2124 ".FAPIBuildGlyph")) < 0) {
2125 return code;
2126 }
2127 }
2128
2129 if (!
2130 ((r_type(&(pdata->BuildChar)) != t_null
2131 && pdata->BuildChar.value.pname && build.BuildChar.value.pname
2132 && name_index(imemory, &pdata->BuildChar) == name_index(imemory,
2133 &build.
2134 BuildChar))
2135 || (r_type(&(pdata->BuildGlyph)) != t_null
2136 && pdata->BuildGlyph.value.pname && build.BuildGlyph.value.pname
2137 && name_index(imemory, &pdata->BuildGlyph) == name_index(imemory,
2138 &build.
2139 BuildGlyph))))
2140 {
2141
2142 if (has_buildchar == true) {
2143 ref_assign_new(&pdata->BuildChar, &build.BuildChar);
2144 }
2145 else {
2146 make_null(&pdata->BuildChar);
2147 }
2148
2149 if (has_buildglyph == true) {
2150 ref_assign_new(&pdata->BuildGlyph, &build.BuildGlyph);
2151 }
2152 else {
2153 make_null(&pdata->BuildGlyph);
2154 }
2155 if (v != NULL) {
2156 font_file_path =
2157 ref_to_string(v, imemory_global, "font file path");
2158 }
2159
2160 code =
2161 FAPI_refine_font(i_ctx_p, op - 1, pfont, subfont,
2162 font_file_path);
2163
2164 memcpy(&I->initial_FontMatrix, &pbfont->FontMatrix,
2165 sizeof(gs_matrix));
2166
2167 if (font_file_path != NULL) {
2168 gs_free_string(imemory_global, (byte *) font_file_path,
2169 r_size(v) + 1, "font file path");
2170 }
2171 }
2172 pop(1);
2173 return code;
2174 }
2175
2176 static ulong
array_find(const gs_memory_t * mem,ref * Encoding,ref * char_name)2177 array_find(const gs_memory_t *mem, ref *Encoding, ref *char_name)
2178 {
2179 ulong n = r_size(Encoding), i;
2180 ref v;
2181
2182 for (i = 0; i < n; i++)
2183 if (array_get(mem, Encoding, i, &v) < 0)
2184 break;
2185 else if (r_type(char_name) == r_type(&v)
2186 && char_name->value.const_pname == v.value.const_pname)
2187 return i;
2188 return 0;
2189 }
2190
2191 static int
zfapi_finish_render(i_ctx_t * i_ctx_p)2192 zfapi_finish_render(i_ctx_t *i_ctx_p)
2193 {
2194 os_ptr op = osp;
2195 gs_font *pfont;
2196 int code = font_param(op - 1, &pfont);
2197
2198 if (code == 0) {
2199 gs_font_base *pbfont = (gs_font_base *) pfont;
2200 gs_fapi_server *I = pbfont->FAPI;
2201 gs_text_enum_t *penum = op_show_find(i_ctx_p);
2202
2203 gs_fapi_set_servers_client_data(imemory, NULL, i_ctx_p);
2204
2205 code = gs_fapi_finish_render(pfont, igs, penum, I);
2206 pop(2);
2207 I->release_char_data(I);
2208 }
2209 return code;
2210 }
2211
2212 static int
ps_fapi_set_cache(gs_text_enum_t * penum,const gs_font_base * pbfont,const gs_string * char_name,int cid,const double pwidth[2],const gs_rect * pbbox,const double Metrics2_sbw_default[4],bool * imagenow)2213 ps_fapi_set_cache(gs_text_enum_t *penum, const gs_font_base *pbfont,
2214 const gs_string *char_name, int cid,
2215 const double pwidth[2], const gs_rect *pbbox,
2216 const double Metrics2_sbw_default[4], bool *imagenow)
2217 {
2218 i_ctx_t *i_ctx_p = (i_ctx_t *) pbfont->FAPI->client_ctx_p;
2219 op_proc_t exec_cont = 0; /* dummy - see below */
2220 int code = 0;
2221
2222 if (cid < 0) {
2223 ref cname;
2224
2225 make_string(&cname, avm_foreign | a_readonly, char_name->size,
2226 char_name->data);
2227 code =
2228 zchar_set_cache(i_ctx_p, pbfont, &cname, NULL, pwidth, pbbox,
2229 zfapi_finish_render, &exec_cont,
2230 Metrics2_sbw_default);
2231 }
2232 else {
2233 ref cidref;
2234
2235 make_int(&cidref, cid);
2236 code = zchar_set_cache(i_ctx_p, pbfont, &cidref, NULL, pwidth, pbbox,
2237 zfapi_finish_render, &exec_cont,
2238 Metrics2_sbw_default);
2239 }
2240
2241 if (code >= 0 && exec_cont != NULL) {
2242 *imagenow = true;
2243 }
2244 else {
2245 *imagenow = false;
2246 }
2247 /* We ignore the value of exec_cont here, and leave it up to
2248 * gs_fapi_do_char() to do the "right" thing based on the
2249 * return value
2250 */
2251 return (code);
2252 }
2253
2254
2255 static const byte *
find_substring(const byte * where,int length,const char * what)2256 find_substring(const byte *where, int length, const char *what)
2257 {
2258 int l = strlen(what);
2259 int n = length - l;
2260 const byte *p = where;
2261
2262 for (; n >= 0; n--, p++)
2263 if (!memcmp(p, what, l))
2264 return p;
2265 return NULL;
2266 }
2267
2268 static int
ps_get_glyphname_or_cid(gs_text_enum_t * penum,gs_font_base * pbfont,gs_string * charstring,gs_string * name,int ccode,gs_string * enc_char_name,char * font_file_path,gs_fapi_char_ref * cr,bool bCID)2269 ps_get_glyphname_or_cid(gs_text_enum_t *penum,
2270 gs_font_base *pbfont, gs_string *charstring,
2271 gs_string *name, int ccode,
2272 gs_string *enc_char_name, char *font_file_path,
2273 gs_fapi_char_ref *cr, bool bCID)
2274 {
2275 ref *pdr = pfont_dict(pbfont);
2276 int client_char_code = ccode;
2277 ref char_name, cname_str;
2278 int code = 0;
2279 gs_fapi_server *I = pbfont->FAPI;
2280 bool is_TT_from_type42 = (pbfont->FontType == ft_TrueType && font_file_path == NULL);
2281 bool is_glyph_index = false;
2282 bool is_embedded_type1 =
2283 ((pbfont->FontType == ft_encrypted
2284 || pbfont->FontType == ft_encrypted2) && font_file_path == NULL);
2285 i_ctx_t *i_ctx_p = (i_ctx_t *) I->client_ctx_p;
2286 bool unicode_cp = false;
2287
2288 /* Obtain the character name : */
2289 if (bCID) {
2290 if (pbfont->FontType == ft_CID_TrueType && font_file_path) {
2291 ref *pdr2, *fidr, *dummy;
2292 pdr2 = pfont_dict(gs_rootfont(igs));
2293 if (dict_find_string(pdr2, "FontInfo", &fidr) > 0 &&
2294 dict_find_string(fidr, "GlyphNames2Unicode", &dummy) > 0)
2295 {
2296 unsigned char uc[4] = {0};
2297 unsigned int cc = 0;
2298 int i, l;
2299 if (penum->text.operation & TEXT_FROM_SINGLE_CHAR) {
2300 cc = penum->text.data.d_char;
2301 } else if (penum->text.operation & TEXT_FROM_SINGLE_GLYPH) {
2302 cc = penum->text.data.d_glyph - GS_MIN_CID_GLYPH;
2303 }
2304 else {
2305 byte *c = (byte *)&penum->text.data.bytes[penum->index - penum->bytes_decoded];
2306 for (i = 0; i < penum->bytes_decoded ; i++) {
2307 cc |= c[i] << ((penum->bytes_decoded - 1) - i) * 8;
2308 }
2309 }
2310 l = ((gs_font_base *)gs_rootfont(igs))->procs.decode_glyph(gs_rootfont(igs), cc + GS_MIN_CID_GLYPH, ccode, (unsigned short *)uc, sizeof(uc));
2311 if (l > 0 && l < sizeof(uc)) {
2312 cc = 0;
2313 for (i = 0; i < l; i++) {
2314 cc |= uc[l - 1 - i] << (i * 8);
2315 }
2316 ccode = cc;
2317 unicode_cp = true;
2318 }
2319 }
2320 }
2321 client_char_code = ccode;
2322 make_null(&char_name);
2323 enc_char_name->data = NULL;
2324 enc_char_name->size = 0;
2325 }
2326 else {
2327 if (ccode >= 0) {
2328 /* Translate from PS encoding to char name : */
2329 ref *Encoding;
2330
2331 client_char_code = ccode;
2332 if (dict_find_string(pdr, "Encoding", &Encoding) > 0 &&
2333 (r_has_type(Encoding, t_array) ||
2334 r_has_type(Encoding, t_shortarray)
2335 || r_has_type(Encoding, t_mixedarray))) {
2336 if (array_get(imemory, Encoding, client_char_code, &char_name)
2337 < 0)
2338 if ((code =
2339 name_ref(imemory, (const byte *)".notdef", 7,
2340 &char_name, -1)) < 0)
2341 return code;
2342 }
2343 else {
2344 return_error(gs_error_invalidfont);
2345 }
2346 }
2347 else {
2348 code =
2349 names_ref(imemory->gs_lib_ctx->gs_name_table,
2350 (const byte *)name->data, name->size, &char_name,
2351 0);
2352
2353 }
2354 /* We need to store the name as we get it (from the Encoding array), in case it's
2355 * had the name extended (with "~GS~xx"), we'll remove the extension before passing
2356 * it to the renderer for a disk based font. But the metrics dictionary may have
2357 * been constructed using the extended name....
2358 */
2359 if (!r_has_type(&char_name, t_name))
2360 return_error(gs_error_invalidfont);
2361 name_string_ref(imemory, &char_name, &cname_str);
2362 enc_char_name->data = cname_str.value.bytes;
2363 enc_char_name->size = r_size(&cname_str);
2364 }
2365
2366 /* Obtain the character code or glyph index : */
2367 cr->char_codes_count = 1;
2368 if (bCID) {
2369 if (font_file_path != NULL) {
2370 ref *Decoding, *TT_cmap = NULL, *SubstNWP;
2371 ref src_type, dst_type;
2372 uint c = 0;
2373
2374 is_glyph_index = true;
2375
2376 if (dict_find_string(pdr, "Decoding", &Decoding) <= 0
2377 || !r_has_type(Decoding, t_dictionary))
2378 return_error(gs_error_invalidfont);
2379 if (dict_find_string(pdr, "SubstNWP", &SubstNWP) <= 0
2380 || !r_has_type(SubstNWP, t_array))
2381 return_error(gs_error_invalidfont);
2382 if (dict_find_string(pdr, "TT_cmap", &TT_cmap) <= 0
2383 || !r_has_type(TT_cmap, t_dictionary)) {
2384 ref *DecodingArray, char_code, char_code1, ih;
2385 int i = client_char_code % 256, n;
2386
2387 make_int(&ih, client_char_code / 256);
2388 /* Check the Decoding array for this block of CIDs */
2389 if (dict_find(Decoding, &ih, &DecodingArray) <= 0
2390 || !r_has_type(DecodingArray, t_array)
2391 || array_get(imemory, DecodingArray, i, &char_code) < 0) {
2392 return_error(gs_error_invalidfont);
2393 }
2394
2395 /* Check the Decoding entry */
2396 if (r_has_type(&char_code, t_integer)) {
2397 n = 1;
2398 }
2399 else if (r_has_type(&char_code, t_array)) {
2400 DecodingArray = &char_code;
2401 i = 0;
2402 n = r_size(DecodingArray);
2403 }
2404 else {
2405 return_error(gs_error_invalidfont);
2406 }
2407
2408 for (; n--; i++) {
2409 if (array_get(imemory, DecodingArray, i, &char_code1) < 0
2410 || !r_has_type(&char_code1, t_integer)) {
2411 return_error(gs_error_invalidfont);
2412 }
2413
2414 c = char_code1.value.intval;
2415 I->check_cmap_for_GID(I, &c);
2416 if (c != 0)
2417 break;
2418 }
2419 }
2420 else {
2421 ref *CIDSystemInfo;
2422 ref *Ordering;
2423 ref *fdict, *CMapDict, *CMapName, *WMode, CMapNameStr;
2424 char *cmapnm = NULL;
2425 int cmapnmlen = 0;
2426 int wmode = 0;
2427 /* leave off the -H or -V */
2428 const char * const utfcmap = "Identity-UTF16";
2429 int utfcmaplen = strlen(utfcmap);
2430
2431 fdict = pfont_dict(gs_rootfont(igs));
2432 code = dict_find_string(fdict, "CMap", &CMapDict);
2433 if (code > 0 && r_has_type(CMapDict, t_dictionary)) {
2434 code = dict_find_string(CMapDict, "WMode", &WMode);
2435 if (code > 0 && r_has_type(WMode, t_integer)) {
2436 wmode = WMode->value.intval;
2437 }
2438 code = dict_find_string(CMapDict, "CMapName", &CMapName);
2439 if (code > 0 && r_has_type(CMapName, t_name)) {
2440 name_string_ref(imemory, CMapName, &CMapNameStr);
2441 cmapnm = (char *)CMapNameStr.value.bytes;
2442 cmapnmlen = r_size(&CMapNameStr);
2443 }
2444 }
2445 /* We only have to lookup the char code if we're *not* using an identity ordering
2446 with the exception of Identity-UTF16 which is a different beast altogether */
2447 if (unicode_cp || (cmapnmlen > 0 && !strncmp(cmapnm, utfcmap, cmapnmlen > utfcmaplen ? utfcmaplen : cmapnmlen))
2448 || (dict_find_string(pdr, "CIDSystemInfo", &CIDSystemInfo) > 0
2449 && r_has_type(CIDSystemInfo, t_dictionary)
2450 && dict_find_string(CIDSystemInfo, "Ordering",
2451 &Ordering) > 0
2452 && r_has_type(Ordering, t_string)
2453 && strncmp((const char *)Ordering->value.bytes,
2454 "Identity", 8) != 0)) {
2455
2456 if ((code =
2457 cid_to_TT_charcode(imemory, Decoding, TT_cmap,
2458 SubstNWP, client_char_code, &c,
2459 &src_type, &dst_type)) < 0) {
2460 return code;
2461 }
2462 }
2463 else {
2464 if (pbfont->FontType == ft_CID_TrueType) {
2465 c = ((gs_font_cid2 *)pbfont)->cidata.CIDMap_proc(((gs_font_cid2 *)pbfont),
2466 client_char_code + GS_MIN_CID_GLYPH);
2467 }
2468 else {
2469 c = client_char_code;
2470 }
2471 }
2472 if (pbfont->FontType == ft_CID_TrueType)
2473 c = ((gs_font_cid2 *)pbfont)->data.substitute_glyph_index_vertical((gs_font_type42 *)pbfont, c, wmode, ccode);
2474 }
2475 if (pbfont->FontType == ft_CID_TrueType && c == 0 && TT_cmap) {
2476 ref cc32;
2477 ref *gid;
2478 make_int(&cc32, 32);
2479 if (dict_find(TT_cmap, &cc32, &gid) > 0)
2480 c = gid->value.intval;
2481 }
2482 cr->char_codes[0] = c;
2483 /* fixme : process the narrow/wide/proportional mapping type,
2484 using src_type, dst_type. Should adjust the 'matrix' above.
2485 Call get_font_proportional_feature for proper choice.
2486 */
2487 }
2488 else {
2489 ref *CIDMap;
2490 byte *Map;
2491 int c_code = client_char_code;
2492 int gdb = 2;
2493 int i;
2494 ref *GDBytes = NULL;
2495
2496 if ((dict_find_string(pdr, "GDBytes", &GDBytes) > 0)
2497 && r_has_type(GDBytes, t_integer)) {
2498 gdb = GDBytes->value.intval;
2499 }
2500
2501 /* The PDF Reference says that we should use a CIDToGIDMap, but the PDF
2502 * interpreter converts this into a CIDMap (see pdf_font.ps, processCIDToGIDMap)
2503 */
2504 if (dict_find_string(pdr, "CIDMap", &CIDMap) > 0
2505 && !r_has_type(CIDMap, t_name) && (r_has_type(CIDMap, t_array)
2506 || r_has_type(CIDMap,
2507 t_string))) {
2508
2509 if (r_has_type(CIDMap, t_array)) {
2510
2511 /* Too big for single string, so its an array of 2 strings */
2512 code = string_array_access_proc(pbfont->memory, CIDMap, 1,
2513 client_char_code * gdb, gdb,
2514 NULL, NULL,
2515 (const byte **)&Map);
2516 }
2517 else {
2518 if (CIDMap->tas.rsize <= c_code * gdb) {
2519 c_code = 0;
2520 }
2521 Map = &CIDMap->value.bytes[c_code * gdb];
2522 }
2523 cr->char_codes[0] = 0;
2524 is_glyph_index = true;
2525 if (code >= 0) {
2526 for (i = 0; i < gdb; i++) {
2527 cr->char_codes[0] = (cr->char_codes[0] << 8) + Map[i];
2528 }
2529 }
2530 else {
2531 ref *cstr, *refcode;
2532 code = dict_find_string(pdr, "CharStrings", &cstr);
2533 if (code > 0) {
2534 code = dict_find_string(cstr, ".notdef", &refcode);
2535 if (code > 0) {
2536 cr->char_codes[0] = refcode->value.intval;
2537 }
2538 }
2539 }
2540 }
2541 else
2542 cr->char_codes[0] = client_char_code;
2543 }
2544 }
2545 else if (is_TT_from_type42) {
2546 /* This font must not use 'cmap', so compute glyph index from CharStrings : */
2547 ref *CharStrings, *glyph_index;
2548
2549 if (dict_find_string(pdr, "CharStrings", &CharStrings) <= 0
2550 || !r_has_type(CharStrings, t_dictionary))
2551 return_error(gs_error_invalidfont);
2552 if ((dict_find(CharStrings, &char_name, &glyph_index) <= 0)
2553 || r_has_type(glyph_index, t_null)) {
2554 #ifdef DEBUG
2555 ref *pvalue;
2556
2557 if (gs_debug_c('1')
2558 && (dict_find_string(systemdict, "QUIET", &pvalue)) > 0
2559 && (r_has_type(pvalue, t_boolean)
2560 && pvalue->value.boolval == false)) {
2561 char *glyphn;
2562
2563 name_string_ref(imemory, &char_name, &char_name);
2564
2565 glyphn =
2566 ref_to_string(&char_name, imemory,
2567 "ps_get_glyphname_or_cid");
2568 if (glyphn) {
2569 dmprintf2(imemory, " Substituting .notdef for %s in the font %s \n",
2570 glyphn, pbfont->font_name.chars);
2571 gs_free_string(imemory, (byte *) glyphn,
2572 strlen(glyphn) + 1,
2573 "ps_get_glyphname_or_cid");
2574 }
2575 }
2576 #endif
2577
2578 cr->char_codes[0] = 0; /* .notdef */
2579 if ((code =
2580 name_ref(imemory, (const byte *)".notdef", 7, &char_name,
2581 -1)) < 0)
2582 return code;
2583 }
2584 else if (r_has_type(glyph_index, t_integer)) {
2585 cr->char_codes[0] = glyph_index->value.intval;
2586 }
2587 else {
2588 #if 1 /* I can't find this ever being used, no idea what it's for..... */
2589 os_ptr op = osp;
2590
2591 /* Check execution stack has space for BuldChar proc and finish_render */
2592 check_estack(2);
2593 /* check space and duplicate the glyph index for BuildChar */
2594 check_op(1);
2595 push(1);
2596 ref_assign_inline(op, op - 1);
2597 /* Come back to fapi_finish_render after running the BuildChar */
2598 push_op_estack(zfapi_finish_render);
2599 ++esp;
2600 ref_assign(esp, glyph_index);
2601 return o_push_estack;
2602 #else
2603 return (gs_error_invalidfont);
2604 #endif
2605 }
2606 is_glyph_index = true;
2607 }
2608 else if (is_embedded_type1) {
2609 /* Since the client passes charstring by callback using I->ff.char_data,
2610 the client doesn't need to provide a good cr here.
2611 Perhaps since UFST uses char codes as glyph cache keys (UFST 4.2 cannot use names),
2612 we provide font char codes equal to document's char codes.
2613 This trick assumes that Encoding can't point different glyphs
2614 for same char code. The last should be true due to
2615 PLRM3, "5.9.4 Subsetting and Incremental Definition of Glyphs".
2616 */
2617 if (ccode >= 0) {
2618 cr->char_codes[0] = client_char_code;
2619 }
2620 else {
2621 /*
2622 * Reverse Encoding here, because it can be an incremental one.
2623 * Note that this can cause problems with UFST (see the comment above),
2624 * if the encoding doesn't contain the glyph name rendered with glyphshow.
2625 */
2626 ref *Encoding;
2627 ref glyph;
2628
2629 if ((code = name_ref(pbfont->memory, name->data, name->size, &glyph, false)) < 0)
2630 return code;
2631
2632 if (dict_find_string(osp - 1, "Encoding", &Encoding) > 0) {
2633 cr->char_codes[0] =
2634 (uint) array_find(imemory, Encoding, &glyph);
2635 }
2636 else
2637 return_error(gs_error_invalidfont);
2638 }
2639 }
2640 else { /* a non-embedded font, i.e. a disk font */
2641 bool can_retrieve_char_by_name = false;
2642 const byte *p;
2643
2644 obj_string_data(imemory, &char_name, &cr->char_name,
2645 &cr->char_name_length);
2646 p = find_substring(cr->char_name, cr->char_name_length,
2647 gx_extendeg_glyph_name_separator);
2648 if (p != NULL) {
2649 cr->char_name_length = p - cr->char_name;
2650 if ((code = name_ref(pbfont->memory, cr->char_name,
2651 cr->char_name_length, &char_name, true)) < 0)
2652 return code;
2653 }
2654 if ((code =
2655 renderer_retcode(imemory, I,
2656 I->can_retrieve_char_by_name(I, &I->ff, cr,
2657 &can_retrieve_char_by_name)))
2658 < 0)
2659 return code;
2660
2661 if (!can_retrieve_char_by_name) {
2662 /* Translate from char name to encoding used with 3d party font technology : */
2663 ref *Decoding, *char_code;
2664
2665 if (dict_find_string(osp - 1, "Decoding", &Decoding) > 0
2666 && r_has_type(Decoding, t_dictionary)) {
2667 if (dict_find(Decoding, &char_name, &char_code) > 0) {
2668 code = 0;
2669 if (r_has_type(char_code, t_integer)) {
2670 int c_code;
2671 int_param(char_code, 0xFFFF, &c_code);
2672 cr->char_codes[0] = (gs_glyph)c_code;
2673 }
2674 else if (r_has_type(char_code, t_array)
2675 || r_has_type(char_code, t_shortarray)) {
2676 int i;
2677 ref v;
2678
2679 cr->char_codes_count = r_size(char_code);
2680 if (cr->char_codes_count > count_of(cr->char_codes))
2681 code = gs_note_error(gs_error_rangecheck);
2682 if (code >= 0) {
2683 for (i = 0; i < cr->char_codes_count; i++) {
2684 code = array_get(imemory, char_code, i, &v);
2685 if (code < 0)
2686 break;
2687 if (!r_has_type(char_code, t_integer)) {
2688 code = gs_note_error(gs_error_rangecheck);
2689 break;
2690 }
2691 cr->char_codes[i] = v.value.intval;
2692 }
2693 }
2694 }
2695 else {
2696 code = gs_note_error(gs_error_rangecheck);
2697 }
2698 if (code < 0) {
2699 char buf[16];
2700 int l = cr->char_name_length;
2701
2702 if (l > sizeof(buf) - 1) {
2703 l = sizeof(buf) - 1;
2704 }
2705 memcpy(buf, cr->char_name, l);
2706 buf[l] = 0;
2707 emprintf1(imemory,
2708 "Wrong decoding entry for the character '%s'.\n",
2709 buf);
2710 return_error(gs_error_rangecheck);
2711 }
2712 }
2713 }
2714 }
2715 }
2716
2717 /* Provide glyph data for renderer : */
2718 /* Occasionally, char_name is already a glyph index to pass to the rendering engine
2719 * so don't treat it as a name object.
2720 * I believe this will only happen with a TTF/Type42, but checking the object type
2721 * is cheap, and covers all font type eventualities.
2722 */
2723 if (!I->ff.is_cid && r_has_type(&char_name, t_name)) {
2724 ref sname;
2725
2726 name_string_ref(imemory, &char_name, &sname);
2727 I->ff.char_data = sname.value.const_bytes;
2728 I->ff.char_data_len = r_size(&sname);
2729 }
2730 else if (I->ff.is_type1) {
2731 I->ff.char_data = charstring;
2732 }
2733
2734 cr->is_glyph_index = is_glyph_index;
2735 cr->client_char_code = client_char_code;
2736
2737 return (code);
2738 }
2739
2740
2741 static int
FAPI_char(i_ctx_t * i_ctx_p,bool bBuildGlyph,ref * charstring)2742 FAPI_char(i_ctx_t *i_ctx_p, bool bBuildGlyph, ref *charstring)
2743 { /* Stack : <font> <code|name> --> - */
2744 os_ptr op = osp;
2745 ref *pdr = op - 1;
2746 ref *v;
2747 char *font_file_path = NULL;
2748 gs_font *pfont;
2749 int code = font_param(osp - 1, &pfont);
2750
2751 if (code == 0) {
2752 gs_font_base *pbfont = (gs_font_base *) pfont;
2753 bool bCID = (FAPI_ISCIDFONT(pbfont) || charstring != NULL);
2754 int subfont;
2755 gs_fapi_server *I = pbfont->FAPI;
2756 gs_text_enum_t *penum = op_show_find(i_ctx_p);
2757 gs_string char_string, *c_string_p = NULL;
2758 gs_string char_name, *c_name_p = NULL;
2759 int cindex = -1;
2760 ref gname;
2761
2762 if (I == NULL)
2763 return_error(gs_error_invalidfont);
2764
2765 /* initialise the FAPI font, this includes language specific stuff */
2766 I->ff = ps_ff_stub;
2767
2768 I->client_ctx_p = i_ctx_p;
2769
2770 if (bBuildGlyph && !bCID) {
2771 if (r_type(op) != t_name) {
2772 name_enter_string(imemory, ".notdef", op);
2773 }
2774 check_type(*op, t_name);
2775
2776 name_string_ref(imemory, op, &gname);
2777 c_name_p = &char_name;
2778 c_name_p->data = gname.value.bytes;
2779 c_name_p->size = r_size(&gname);
2780
2781 }
2782 else {
2783 if (bBuildGlyph && pbfont->FontType == ft_CID_TrueType
2784 && r_has_type(op, t_name)) {
2785 ref *chstrs, *chs;
2786
2787 /* This logic is lifted from %Type11BuildGlyph in gs_cidfn.ps
2788 * Note we only have to deal with mistakenly being given a name object
2789 * here, the out of range CID is handled later
2790 */
2791 if ((dict_find_string(op - 1, "CharStrings", &chstrs)) <= 0) {
2792 return_error(gs_error_undefined);
2793 }
2794
2795 if ((dict_find_string(chstrs, ".notdef", &chs)) <= 0) {
2796 return_error(gs_error_undefined);
2797 }
2798 ref_assign_inline(op, chs);
2799 }
2800
2801 make_null(&gname);
2802 check_type(*op, t_integer);
2803 int_param(op, 0xFFFF, &cindex);
2804 }
2805
2806 if (dict_find_string(pdr, "SubfontId", &v) > 0
2807 && r_has_type(v, t_integer))
2808 subfont = v->value.intval;
2809 else
2810 subfont = 0;
2811
2812 if (dict_find_string(osp - 1, "Path", &v) > 0
2813 && r_has_type(v, t_string)) {
2814 font_file_path = ref_to_string(v, imemory, "font file path");
2815 }
2816
2817 if (charstring) {
2818 c_string_p = &char_string;
2819 c_string_p->data = charstring->value.bytes;
2820 c_string_p->size = r_size(charstring);
2821 }
2822
2823 code =
2824 gs_fapi_do_char(pfont, igs, penum, font_file_path,
2825 bBuildGlyph, c_string_p, c_name_p, (gs_char)cindex, (gs_glyph)cindex,
2826 subfont);
2827 if (font_file_path != NULL) {
2828 gs_free_string(imemory, (byte *) font_file_path, r_size(v) + 1,
2829 "font file path");
2830 }
2831 /* This handles the situation where a charstring has been replaced with a PS procedure.
2832 * against the rules, but not *that* rare.
2833 * It's also something that GS does internally to simulate font styles.
2834 */
2835 if (code == gs_error_unregistered) {
2836 os_ptr op = osp;
2837 ref *proc = NULL, gname;
2838
2839 if (I->ff.is_type1
2840 && (get_charstring(&I->ff, cindex, &proc, &gname) >= 0)
2841 && proc != NULL && (r_has_type(proc, t_array)
2842 || r_has_type(proc, t_mixedarray))) {
2843 push(2);
2844 ref_assign(op - 1, &gname);
2845 ref_assign(op, proc);
2846 return (zchar_exec_char_proc(i_ctx_p));
2847 }
2848 else {
2849 return_error(gs_error_invalidfont);
2850 }
2851 }
2852 }
2853 /* We've already imaged teh glyph, pop the operands */
2854 if (code == 0)
2855 pop(2);
2856 return code;
2857 }
2858
2859 static int
zFAPIBuildGlyph9(i_ctx_t * i_ctx_p)2860 zFAPIBuildGlyph9(i_ctx_t *i_ctx_p)
2861 {
2862 /* The alghorithm is taken from %Type9BuildGlyph - see gs_cidfn.ps . */
2863 os_ptr lop, op = osp;
2864 int cid, code;
2865 avm_space s = ialloc_space(idmemory);
2866 ref font9 = *pfont_dict(gs_currentfont(igs));
2867 ref *rFDArray, f;
2868 int font_index;
2869
2870 check_type(op[0], t_integer);
2871 check_type(op[-1], t_dictionary);
2872 cid = op[0].value.intval;
2873 push(2);
2874 op[-1] = *pfont_dict(gs_currentfont(igs));
2875 op[0] = op[-2]; /* <font0> <cid> <font9> <cid> */
2876 ialloc_set_space(idmemory, (r_is_local(op - 3) ? avm_global : avm_local)); /* for ztype9mapcid */
2877
2878 /* stack: <font0> <cid> <font9> <cid> */
2879 if ((code = ztype9mapcid(i_ctx_p)) < 0)
2880 return code; /* <font0> <cid> <charstring> <font_index> */
2881 /* fixme: what happens if the charstring is absent ?
2882 Can FDArray contain 'null' (see %Type9BuildGlyph in gs_cidfn.ps)? */
2883 font_index = op[0].value.intval;
2884 if (dict_find_string(&font9, "FDArray", &rFDArray) <= 0
2885 || r_type(rFDArray) != t_array)
2886 return_error(gs_error_invalidfont);
2887 if (array_get(imemory, rFDArray, font_index, &f) < 0
2888 || r_type(&f) != t_dictionary)
2889 return_error(gs_error_invalidfont);
2890
2891 op[0] = op[-2];
2892 op[-2] = op[-1]; /* Keep the charstring on ostack for the garbager. */
2893 op[-1] = f; /* <font0> <charstring> <subfont> <cid> */
2894 if ((code = FAPI_char(i_ctx_p, true, op - 2)) < 0)
2895 return code;
2896 /* stack: <font0> <charstring> */
2897
2898 lop = osp;
2899 if (code == 5) {
2900 int i, ind = (lop - op);
2901
2902 op = osp;
2903
2904 for (i = ind; i >= 0; i--) {
2905 op[-i - 2] = op[-i];
2906 }
2907 pop(2);
2908 }
2909 else if (code < 0) { /* <font0> <dirty> <dirty> <dirty> */
2910 /* Adjust ostack for the correct error handling : */
2911 make_int(op - 2, cid);
2912 pop(2); /* <font0> <cid> */
2913 }
2914 else if (code != 5) { /* <font0> <dirty> */
2915
2916
2917 pop(2); /* */
2918 /* Note that this releases the charstring, and it may be garbage-collected
2919 before the interpreter calls fapi_finish_render. This requires the server
2920 to keep glyph raster internally between calls to get_char_raster_metrics
2921 and get_char_raster. Perhaps UFST cannot provide metrics without
2922 building a raster, so this constraint actually goes from UFST.
2923 */
2924 }
2925 ialloc_set_space(idmemory, s);
2926 return code;
2927 }
2928
2929 /* <font> <code> .FAPIBuildChar - */
2930 static int
zFAPIBuildChar(i_ctx_t * i_ctx_p)2931 zFAPIBuildChar(i_ctx_t *i_ctx_p)
2932 {
2933 return FAPI_char(i_ctx_p, false, NULL);
2934 }
2935
2936 /* non-CID : <font> <code> .FAPIBuildGlyph - */
2937 /* CID : <font> <name> .FAPIBuildGlyph - */
2938 static int
zFAPIBuildGlyph(i_ctx_t * i_ctx_p)2939 zFAPIBuildGlyph(i_ctx_t *i_ctx_p)
2940 {
2941 return FAPI_char(i_ctx_p, true, NULL);
2942 }
2943
2944
2945 /* <font_dict> .FAPIpassfont bool <font_dict> */
2946 /* must insert /FAPI to font dictionary */
2947 static int
zFAPIpassfont(i_ctx_t * i_ctx_p)2948 zFAPIpassfont(i_ctx_t *i_ctx_p)
2949 {
2950 os_ptr op = osp;
2951 gs_font *pfont;
2952 int code;
2953 char *font_file_path = NULL;
2954 ref *v;
2955 char *xlatmap = NULL;
2956 char *fapi_request = NULL;
2957 char *fapi_id = NULL;
2958 ref reqstr;
2959 int subfont;
2960
2961 /* Normally embedded fonts have no Path, but if a CID font is
2962 * emulated with a TT font, and it is hooked with FAPI,
2963 * the path presents and is neccessary to access the full font data.
2964 */
2965 check_type(*op, t_dictionary);
2966
2967 code = font_param(osp, &pfont);
2968 if (code < 0)
2969 return code;
2970
2971 if (dict_find_string(op, "SubfontId", &v) > 0
2972 && r_has_type(v, t_integer))
2973 subfont = v->value.intval;
2974 else
2975 subfont = 0;
2976
2977 code = FAPI_get_xlatmap(i_ctx_p, &xlatmap); /* Useful for emulated fonts hooked with FAPI. */
2978 if (code < 0)
2979 return code;
2980
2981 /* If the font dictionary contains a FAPIPlugInReq key, the the PS world wants us
2982 * to try to use a specific FAPI plugin, so find it, and try it....
2983 */
2984 if (dict_find_string(op, "FAPIPlugInReq", &v) > 0 && r_type(v) == t_name) {
2985
2986 name_string_ref(imemory, v, &reqstr);
2987
2988 fapi_request = ref_to_string(&reqstr, imemory, "zFAPIpassfont");
2989 }
2990
2991 if (dict_find_string(op, "Path", &v) > 0 && r_has_type(v, t_string))
2992 font_file_path = ref_to_string(v, imemory_global, "font file path");
2993
2994 gs_fapi_set_servers_client_data(imemory, &ps_ff_stub, i_ctx_p);
2995
2996 code =
2997 gs_fapi_passfont(pfont, subfont, font_file_path, NULL, fapi_request, xlatmap,
2998 &fapi_id, (gs_fapi_get_server_param_callback)ps_get_server_param);
2999
3000 if (font_file_path != NULL)
3001 gs_free_string(imemory_global, (byte *) font_file_path, r_size(v) + 1,
3002 "font file path");
3003
3004 if (fapi_request != NULL)
3005 gs_free_string(imemory, (byte *) fapi_request,
3006 strlen(fapi_request) + 1, "do_FAPIpassfont");
3007 if (code < 0 && code != gs_error_invalidaccess)
3008 return code;
3009
3010 if (code >= 0 && fapi_id != NULL) {
3011 ref FAPI_ID;
3012
3013 if ((code =
3014 name_ref(imemory, (const byte *)fapi_id,
3015 strlen(fapi_id), &FAPI_ID, false)) < 0)
3016 return code;
3017 if ((code = dict_put_string(op, "FAPI", &FAPI_ID, NULL)) < 0)
3018 return code; /* Insert FAPI entry to font dictionary. */
3019 }
3020 push(1);
3021 make_bool(op, (fapi_id != NULL));
3022 return 0;
3023 }
3024
3025 const op_def zfapi_op_defs[] = {
3026 {"1.FAPIavailable", zFAPIavailable},
3027 {"2.FAPIpassfont", zFAPIpassfont},
3028 {"2.FAPIrebuildfont", zFAPIrebuildfont},
3029 {"2.FAPIBuildChar", zFAPIBuildChar},
3030 {"2.FAPIBuildGlyph", zFAPIBuildGlyph},
3031 {"2.FAPIBuildGlyph9", zFAPIBuildGlyph9},
3032 op_def_end(0)
3033 };
3034