1 /* Copyright (C) 1992-2004 artofcode LLC. All rights reserved.
2
3 This software is provided AS-IS with no warranty, either express or
4 implied.
5
6 This software is distributed under license and may not be copied,
7 modified or distributed except as expressly authorized under the terms
8 of the license contained in the file LICENSE in this distribution.
9
10 For more information about licensing, please refer to
11 http://www.ghostscript.com/licensing/. For information on
12 commercial licensing, go to http://www.artifex.com/licensing/ or
13 contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14 San Rafael, CA 94903, U.S.A., +1(415)492-9861.
15 */
16
17 /* $Id: iccfont.c,v 1.11 2004/10/26 02:50:56 giles Exp $ */
18 /* Initialization support for compiled fonts */
19
20 #include "string_.h"
21 #include "ghost.h"
22 #include "gsstruct.h" /* for iscan.h */
23 #include "gscencs.h"
24 #include "gsmatrix.h"
25 #include "gxfont.h" /* for ifont.h */
26 #include "ccfont.h"
27 #include "ierrors.h"
28 #include "ialloc.h"
29 #include "idict.h"
30 #include "ifont.h"
31 #include "iname.h"
32 #include "isave.h" /* for ialloc_ref_array */
33 #include "iutil.h"
34 #include "oper.h"
35 #include "ostack.h" /* for iscan.h */
36 #include "store.h"
37 #include "stream.h" /* for iscan.h */
38 #include "strimpl.h" /* for sfilter.h for picky compilers */
39 #include "sfilter.h" /* for iscan.h */
40 #include "iscan.h"
41
42 /* ------ Private code ------ */
43
44 /* Forward references */
45 private int cfont_ref_from_string(i_ctx_t *, ref *, const char *, uint);
46
47 typedef struct {
48 i_ctx_t *i_ctx_p;
49 const char *str_array;
50 ref next;
51 } str_enum;
52
53 inline private void
init_str_enum(str_enum * pse,i_ctx_t * i_ctx_p,const char * ksa)54 init_str_enum(str_enum *pse, i_ctx_t *i_ctx_p, const char *ksa)
55 {
56 pse->i_ctx_p = i_ctx_p;
57 pse->str_array = ksa;
58 }
59
60 typedef struct {
61 cfont_dict_keys keys;
62 str_enum strings;
63 } key_enum;
64
65 inline private void
init_key_enum(key_enum * pke,i_ctx_t * i_ctx_p,const cfont_dict_keys * pkeys,const char * ksa)66 init_key_enum(key_enum *pke, i_ctx_t *i_ctx_p, const cfont_dict_keys *pkeys,
67 const char *ksa)
68 {
69 pke->keys = *pkeys;
70 init_str_enum(&pke->strings, i_ctx_p, ksa);
71 }
72
73 /* Check for reaching the end of the keys. */
74 inline private bool
more_keys(const key_enum * pke)75 more_keys(const key_enum *pke)
76 {
77 return (pke->keys.num_enc_keys | pke->keys.num_str_keys);
78 }
79
80 /* Get the next string from a string array. */
81 /* Return 1 if it was a string, 0 if it was something else, */
82 /* or an error code. */
83 private int
cfont_next_string(str_enum * pse)84 cfont_next_string(str_enum * pse)
85 {
86 const byte *str = (const byte *)pse->str_array;
87 uint len = (str[0] << 8) + str[1];
88
89 if (len == 0xffff) {
90 make_null(&pse->next);
91 pse->str_array += 2;
92 return 0;
93 } else if (len >= 0xff00) {
94 int code;
95
96 len = ((len & 0xff) << 8) + str[2];
97 code = cfont_ref_from_string(pse->i_ctx_p, &pse->next,
98 pse->str_array + 3, len);
99 if (code < 0)
100 return code;
101 pse->str_array += 3 + len;
102 return 0;
103 }
104 make_const_string(&pse->next, avm_foreign, len, str + 2);
105 pse->str_array += 2 + len;
106 return 1;
107 }
108
109 /* Put the next entry into a dictionary. */
110 /* We know that more_keys(kp) is true. */
111 private int
cfont_put_next(ref * pdict,key_enum * kep,const ref * pvalue)112 cfont_put_next(ref * pdict, key_enum * kep, const ref * pvalue)
113 {
114 i_ctx_t *i_ctx_p = kep->strings.i_ctx_p;
115 cfont_dict_keys * const kp = &kep->keys;
116 ref kname;
117 int code;
118
119 if (pdict->value.pdict == 0) {
120 /* First time, create the dictionary. */
121 code = dict_create(kp->num_enc_keys + kp->num_str_keys +
122 kp->extra_slots, pdict);
123 if (code < 0)
124 return code;
125 }
126 if (kp->num_enc_keys) {
127 const charindex *skp = kp->enc_keys++;
128 gs_glyph glyph = gs_c_known_encode((gs_char)skp->charx, skp->encx);
129 gs_const_string gstr;
130
131 if (glyph == GS_NO_GLYPH)
132 code = gs_note_error(e_undefined);
133 else if ((code = gs_c_glyph_name(glyph, &gstr)) >= 0)
134 code = name_ref(imemory, gstr.data, gstr.size, &kname, 0);
135 kp->num_enc_keys--;
136 } else { /* must have kp->num_str_keys != 0 */
137 code = cfont_next_string(&kep->strings);
138 if (code != 1)
139 return (code < 0 ? code : gs_note_error(e_Fatal));
140 code = name_ref(imemory, kep->strings.next.value.const_bytes,
141 r_size(&kep->strings.next), &kname, 0);
142 kp->num_str_keys--;
143 }
144 if (code < 0)
145 return code;
146 return dict_put(pdict, &kname, pvalue, &i_ctx_p->dict_stack);
147 }
148
149 /* ------ Routines called from compiled font initialization ------ */
150
151 /* Create a dictionary with general ref values. */
152 private int
cfont_ref_dict_create(i_ctx_t * i_ctx_p,ref * pdict,const cfont_dict_keys * kp,cfont_string_array ksa,const ref * values)153 cfont_ref_dict_create(i_ctx_t *i_ctx_p, ref *pdict,
154 const cfont_dict_keys *kp, cfont_string_array ksa,
155 const ref *values)
156 {
157 key_enum kenum;
158 const ref *vp = values;
159
160 init_key_enum(&kenum, i_ctx_p, kp, ksa);
161 pdict->value.pdict = 0;
162 while (more_keys(&kenum)) {
163 const ref *pvalue = vp++;
164 int code = cfont_put_next(pdict, &kenum, pvalue);
165
166 if (code < 0)
167 return code;
168 }
169 r_store_attrs(dict_access_ref(pdict), a_all, kp->dict_attrs);
170 return 0;
171 }
172
173 /* Create a dictionary with string/null values. */
174 private int
cfont_string_dict_create(i_ctx_t * i_ctx_p,ref * pdict,const cfont_dict_keys * kp,cfont_string_array ksa,cfont_string_array kva)175 cfont_string_dict_create(i_ctx_t *i_ctx_p, ref *pdict,
176 const cfont_dict_keys *kp, cfont_string_array ksa,
177 cfont_string_array kva)
178 {
179 key_enum kenum;
180 str_enum senum;
181 uint attrs = kp->value_attrs;
182
183 init_key_enum(&kenum, i_ctx_p, kp, ksa);
184 init_str_enum(&senum, i_ctx_p, kva);
185 pdict->value.pdict = 0;
186 while (more_keys(&kenum)) {
187 int code = cfont_next_string(&senum);
188
189 switch (code) {
190 default: /* error */
191 return code;
192 case 1: /* string */
193 r_set_attrs(&senum.next, attrs);
194 case 0: /* other */
195 ;
196 }
197 code = cfont_put_next(pdict, &kenum, &senum.next);
198 if (code < 0)
199 return code;
200 }
201 r_store_attrs(dict_access_ref(pdict), a_all, kp->dict_attrs);
202 return 0;
203 }
204
205 /* Create a dictionary with number values. */
206 private int
cfont_num_dict_create(i_ctx_t * i_ctx_p,ref * pdict,const cfont_dict_keys * kp,cfont_string_array ksa,const ref * values,const char * lengths)207 cfont_num_dict_create(i_ctx_t *i_ctx_p, ref * pdict,
208 const cfont_dict_keys * kp, cfont_string_array ksa,
209 const ref * values, const char *lengths)
210 {
211 key_enum kenum;
212 const ref *vp = values;
213 const char *lp = lengths;
214 ref vnum;
215
216 init_key_enum(&kenum, i_ctx_p, kp, ksa);
217 pdict->value.pdict = 0;
218 while (more_keys(&kenum)) {
219 int len = (lp == 0 ? 0 : *lp++);
220 int code;
221
222 if (len == 0)
223 vnum = *vp++;
224 else {
225 --len;
226 make_const_array(&vnum, avm_foreign | a_readonly, len, vp);
227 vp += len;
228 }
229 code = cfont_put_next(pdict, &kenum, &vnum);
230 if (code < 0)
231 return code;
232 }
233 r_store_attrs(dict_access_ref(pdict), a_all, kp->dict_attrs);
234 return 0;
235 }
236
237 /* Create an array with name values. */
238 private int
cfont_name_array_create(i_ctx_t * i_ctx_p,ref * parray,cfont_string_array ksa,int size)239 cfont_name_array_create(i_ctx_t *i_ctx_p, ref * parray, cfont_string_array ksa,
240 int size)
241 {
242 int code = ialloc_ref_array(parray, a_readonly, size,
243 "cfont_name_array_create");
244 ref *aptr = parray->value.refs;
245 int i;
246 str_enum senum;
247
248 if (code < 0)
249 return code;
250 init_str_enum(&senum, i_ctx_p, ksa);
251 for (i = 0; i < size; i++, aptr++) {
252 ref nref;
253 int code = cfont_next_string(&senum);
254
255 if (code != 1)
256 return (code < 0 ? code : gs_note_error(e_Fatal));
257 code = name_ref(imemory, senum.next.value.const_bytes,
258 r_size(&senum.next), &nref, 0);
259 if (code < 0)
260 return code;
261 ref_assign_new(aptr, &nref);
262 }
263 return 0;
264 }
265
266 /* Create an array with string/null values. */
267 private int
cfont_string_array_create(i_ctx_t * i_ctx_p,ref * parray,cfont_string_array ksa,int size,uint attrs)268 cfont_string_array_create(i_ctx_t *i_ctx_p, ref * parray,
269 cfont_string_array ksa, int size, uint attrs)
270 {
271 int code = ialloc_ref_array(parray, a_readonly, size,
272 "cfont_string_array_create");
273 ref *aptr = parray->value.refs;
274 int i;
275 str_enum senum;
276
277 if (code < 0)
278 return code;
279 init_str_enum(&senum, i_ctx_p, ksa);
280 for (i = 0; i < size; i++, aptr++) {
281 int code = cfont_next_string(&senum);
282
283 switch (code) {
284 default: /* error */
285 return code;
286 case 1: /* string */
287 r_set_attrs(&senum.next, attrs);
288 case 0: /* other */
289 ;
290 }
291 ref_mark_new(&senum.next);
292 *aptr = senum.next;
293 }
294 return 0;
295 }
296
297 /* Create an array with scalar values. */
298 private int
cfont_scalar_array_create(i_ctx_t * i_ctx_p,ref * parray,const ref * va,int size,uint attrs)299 cfont_scalar_array_create(i_ctx_t *i_ctx_p, ref * parray,
300 const ref *va, int size, uint attrs)
301 {
302 int code = ialloc_ref_array(parray, attrs, size,
303 "cfont_scalar_array_create");
304 ref *aptr = parray->value.refs;
305 uint elt_attrs = attrs | ialloc_new_mask;
306 int i;
307
308 if (code < 0)
309 return code;
310 memcpy(aptr, va, size * sizeof(ref));
311 for (i = 0; i < size; i++, aptr++)
312 r_set_attrs(aptr, elt_attrs);
313 return 0;
314 }
315
316 /* Create a name. */
317 private int
cfont_name_create(i_ctx_t * i_ctx_p,ref * pnref,const char * str)318 cfont_name_create(i_ctx_t *i_ctx_p, ref * pnref, const char *str)
319 {
320 return name_ref(imemory, (const byte *)str, strlen(str), pnref, 0);
321 }
322
323 /* Create an object by parsing a string. */
324 private int
cfont_ref_from_string(i_ctx_t * i_ctx_p,ref * pref,const char * str,uint len)325 cfont_ref_from_string(i_ctx_t *i_ctx_p, ref * pref, const char *str, uint len)
326 {
327 scanner_state sstate;
328 stream s;
329 int code;
330
331 scanner_state_init(&sstate, false);
332 s_init(&s, imemory);
333 sread_string(&s, (const byte *)str, len);
334 code = scan_token(i_ctx_p, &s, pref, &sstate);
335 return (code <= 0 ? code : gs_note_error(e_Fatal));
336 }
337
338 /* ------ Initialization ------ */
339
340 /* Procedure vector passed to font initialization procedures. */
341 private const cfont_procs ccfont_procs = {
342 cfont_ref_dict_create,
343 cfont_string_dict_create,
344 cfont_num_dict_create,
345 cfont_name_array_create,
346 cfont_string_array_create,
347 cfont_scalar_array_create,
348 cfont_name_create,
349 cfont_ref_from_string
350 };
351
352 /* null .getccfont <number-of-fonts> */
353 /* <int> .getccfont <font-object> */
354 private int
zgetccfont(i_ctx_t * i_ctx_p)355 zgetccfont(i_ctx_t *i_ctx_p)
356 {
357 os_ptr op = osp;
358 int code;
359 const ccfont_fproc *fprocs;
360 int nfonts;
361 int index;
362
363 code = ccfont_fprocs(&nfonts, &fprocs);
364 if (code != ccfont_version)
365 return_error(e_invalidfont);
366
367 if (r_has_type(op, t_null)) {
368 make_int(op, nfonts);
369 return 0;
370 }
371 check_type(*op, t_integer);
372 index = op->value.intval;
373 if (index < 0 || index >= nfonts)
374 return_error(e_rangecheck);
375
376 return (*fprocs[index]) (i_ctx_p, &ccfont_procs, op);
377 }
378
379 /* Operator table initialization */
380
381 const op_def ccfonts_op_defs[] =
382 {
383 {"0.getccfont", zgetccfont},
384 op_def_end(0)
385 };
386