1 /* Copyright (C) 1992, 1995, 1997, 1998 Aladdin Enterprises. 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: idparam.c,v 1.9 2004/08/04 19:36:12 stefan Exp $ */
18 /* Utilities for getting parameters out of dictionaries. */
19 #include "memory_.h"
20 #include "string_.h" /* for strlen */
21 #include "ghost.h"
22 #include "ierrors.h"
23 #include "gsmatrix.h" /* for dict_matrix_param */
24 #include "gsuid.h"
25 #include "idict.h"
26 #include "idparam.h" /* interface definition */
27 #include "ilevel.h"
28 #include "imemory.h" /* for iutil.h */
29 #include "iname.h"
30 #include "iutil.h"
31 #include "oper.h" /* for check_proc */
32 #include "store.h" /* for making empty proc */
33
34 /* Get a Boolean parameter from a dictionary. */
35 /* Return 0 if found, 1 if defaulted, <0 if wrong type. */
36 int
dict_bool_param(const ref * pdict,const char * kstr,bool defaultval,bool * pvalue)37 dict_bool_param(const ref * pdict, const char *kstr,
38 bool defaultval, bool * pvalue)
39 {
40 ref *pdval;
41
42 if (pdict == 0 || dict_find_string(pdict, kstr, &pdval) <= 0) {
43 *pvalue = defaultval;
44 return 1;
45 }
46 if (!r_has_type(pdval, t_boolean))
47 return_error(e_typecheck);
48 *pvalue = pdval->value.boolval;
49 return 0;
50 }
51
52 /* Get an integer or null parameter from a dictionary. */
53 /* Return 0 if found, 1 if defaulted, <0 if invalid. */
54 /* If the parameter is null, return 2 without setting *pvalue. */
55 /* Note that the default value may be out of range, in which case */
56 /* a missing value will return e_rangecheck rather than 1. */
57 int
dict_int_null_param(const ref * pdict,const char * kstr,int minval,int maxval,int defaultval,int * pvalue)58 dict_int_null_param(const ref * pdict, const char *kstr, int minval,
59 int maxval, int defaultval, int *pvalue)
60 {
61 ref *pdval;
62 int code;
63 long ival;
64
65 if (pdict == 0 || dict_find_string(pdict, kstr, &pdval) <= 0) {
66 ival = defaultval;
67 code = 1;
68 } else {
69 switch (r_type(pdval)) {
70 case t_integer:
71 ival = pdval->value.intval;
72 break;
73 case t_real:
74 /* Allow an integral real, because Fontographer */
75 /* (which violates the Adobe specs in other ways */
76 /* as well) sometimes generates output that */
77 /* needs this. */
78 if (pdval->value.realval < minval || pdval->value.realval > maxval)
79 return_error(e_rangecheck);
80 ival = (long)pdval->value.realval;
81 if (ival != pdval->value.realval)
82 return_error(e_rangecheck);
83 break;
84 case t_null:
85 return 2;
86 default:
87 return_error(e_typecheck);
88 }
89 code = 0;
90 }
91 if (ival < minval || ival > maxval)
92 return_error(e_rangecheck);
93 *pvalue = (int)ival;
94 return code;
95 }
96 /* Get an integer parameter from a dictionary. */
97 /* Return like dict_int_null_param, but return e_typecheck for null. */
98 int
dict_int_param(const ref * pdict,const char * kstr,int minval,int maxval,int defaultval,int * pvalue)99 dict_int_param(const ref * pdict, const char *kstr, int minval, int maxval,
100 int defaultval, int *pvalue)
101 {
102 int code = dict_int_null_param(pdict, kstr, minval, maxval,
103 defaultval, pvalue);
104
105 return (code == 2 ? gs_note_error(e_typecheck) : code);
106 }
107
108 /* Get an unsigned integer parameter from a dictionary. */
109 /* Return 0 if found, 1 if defaulted, <0 if invalid. */
110 /* Note that the default value may be out of range, in which case */
111 /* a missing value will return e_rangecheck rather than 1. */
112 int
dict_uint_param(const ref * pdict,const char * kstr,uint minval,uint maxval,uint defaultval,uint * pvalue)113 dict_uint_param(const ref * pdict, const char *kstr,
114 uint minval, uint maxval, uint defaultval, uint * pvalue)
115 {
116 ref *pdval;
117 int code;
118 uint ival;
119
120 if (pdict == 0 || dict_find_string(pdict, kstr, &pdval) <= 0) {
121 ival = defaultval;
122 code = 1;
123 } else {
124 check_type_only(*pdval, t_integer);
125 if (pdval->value.intval != (uint) pdval->value.intval)
126 return_error(e_rangecheck);
127 ival = (uint) pdval->value.intval;
128 code = 0;
129 }
130 if (ival < minval || ival > maxval)
131 return_error(e_rangecheck);
132 *pvalue = ival;
133 return code;
134 }
135
136 /* Get a float parameter from a dictionary. */
137 /* Return 0 if found, 1 if defaulted, <0 if wrong type. */
138 int
dict_float_param(const ref * pdict,const char * kstr,floatp defaultval,float * pvalue)139 dict_float_param(const ref * pdict, const char *kstr,
140 floatp defaultval, float *pvalue)
141 {
142 ref *pdval;
143
144 if (pdict == 0 || dict_find_string(pdict, kstr, &pdval) <= 0) {
145 *pvalue = defaultval;
146 return 1;
147 }
148 switch (r_type(pdval)) {
149 case t_integer:
150 *pvalue = (float)pdval->value.intval;
151 return 0;
152 case t_real:
153 *pvalue = pdval->value.realval;
154 return 0;
155 }
156 return_error(e_typecheck);
157 }
158
159 /* Get an integer array from a dictionary. */
160 /* See idparam.h for specification. */
161 int
dict_int_array_check_param(const ref * pdict,const char * kstr,uint len,int * ivec,int under_error,int over_error)162 dict_int_array_check_param(const ref * pdict, const char *kstr, uint len,
163 int *ivec, int under_error, int over_error)
164 {
165 ref *pdval;
166 const ref *pa;
167 int *pi = ivec;
168 uint size;
169 int i;
170
171 if (pdict == 0 || dict_find_string(pdict, kstr, &pdval) <= 0)
172 return 0;
173 if (!r_has_type(pdval, t_array))
174 return_error(e_typecheck);
175 size = r_size(pdval);
176 if (size > len)
177 return_error(over_error);
178 pa = pdval->value.const_refs;
179 for (i = 0; i < size; i++, pa++, pi++) {
180 /* See dict_int_param above for why we allow reals here. */
181 switch (r_type(pa)) {
182 case t_integer:
183 if (pa->value.intval != (int)pa->value.intval)
184 return_error(e_rangecheck);
185 *pi = (int)pa->value.intval;
186 break;
187 case t_real:
188 if (pa->value.realval < min_int ||
189 pa->value.realval > max_int ||
190 pa->value.realval != (int)pa->value.realval
191 )
192 return_error(e_rangecheck);
193 *pi = (int)pa->value.realval;
194 break;
195 default:
196 return_error(e_typecheck);
197 }
198 }
199 return (size == len || under_error >= 0 ? size :
200 gs_note_error(under_error));
201 }
202 int
dict_int_array_param(const ref * pdict,const char * kstr,uint maxlen,int * ivec)203 dict_int_array_param(const ref * pdict, const char *kstr,
204 uint maxlen, int *ivec)
205 {
206 return dict_int_array_check_param(pdict, kstr, maxlen, ivec,
207 0, e_limitcheck);
208 }
209 int
dict_ints_param(const ref * pdict,const char * kstr,uint len,int * ivec)210 dict_ints_param(const ref * pdict, const char *kstr,
211 uint len, int *ivec)
212 {
213 return dict_int_array_check_param(pdict, kstr, len, ivec,
214 e_rangecheck, e_rangecheck);
215 }
216
217 /* Get a float array from a dictionary. */
218 /* Return the element count if OK, <0 if invalid. */
219 /* If the parameter is missing, then if defaultvec is NULL, return 0; */
220 /* if defaultvec is not NULL, copy it into fvec (maxlen elements) */
221 /* and return maxlen. */
222 int
dict_float_array_check_param(const gs_memory_t * mem,const ref * pdict,const char * kstr,uint len,float * fvec,const float * defaultvec,int under_error,int over_error)223 dict_float_array_check_param(const gs_memory_t *mem,
224 const ref * pdict, const char *kstr,
225 uint len, float *fvec, const float *defaultvec,
226 int under_error, int over_error)
227 {
228 ref *pdval;
229 uint size;
230 int code;
231
232 if (pdict == 0 || dict_find_string(pdict, kstr, &pdval) <= 0) {
233 if (defaultvec == NULL)
234 return 0;
235 memcpy(fvec, defaultvec, len * sizeof(float));
236
237 return len;
238 }
239 if (!r_is_array(pdval))
240 return_error(e_typecheck);
241 size = r_size(pdval);
242 if (size > len)
243 return_error(over_error);
244 code = process_float_array(mem, pdval, size, fvec);
245 return (code < 0 ? code :
246 size == len || under_error >= 0 ? size :
247 gs_note_error(under_error));
248 }
249 int
dict_float_array_param(const gs_memory_t * mem,const ref * pdict,const char * kstr,uint maxlen,float * fvec,const float * defaultvec)250 dict_float_array_param(const gs_memory_t *mem,
251 const ref * pdict, const char *kstr,
252 uint maxlen, float *fvec, const float *defaultvec)
253 {
254 return dict_float_array_check_param(mem ,pdict, kstr, maxlen, fvec,
255 defaultvec, 0, e_limitcheck);
256 }
257 int
dict_floats_param(const gs_memory_t * mem,const ref * pdict,const char * kstr,uint maxlen,float * fvec,const float * defaultvec)258 dict_floats_param(const gs_memory_t *mem,
259 const ref * pdict, const char *kstr,
260 uint maxlen, float *fvec, const float *defaultvec)
261 {
262 return dict_float_array_check_param(mem, pdict, kstr, maxlen,
263 fvec, defaultvec,
264 e_rangecheck, e_rangecheck);
265 }
266
267 /*
268 * Get a procedure from a dictionary. If the key is missing,
269 * defaultval = false means substitute t__invalid;
270 * defaultval = true means substitute an empty procedure.
271 * In either case, return 1.
272 */
273 int
dict_proc_param(const ref * pdict,const char * kstr,ref * pproc,bool defaultval)274 dict_proc_param(const ref * pdict, const char *kstr, ref * pproc,
275 bool defaultval)
276 {
277 ref *pdval;
278
279 if (pdict == 0 || dict_find_string(pdict, kstr, &pdval) <= 0) {
280 if (defaultval)
281 make_empty_const_array(pproc, a_readonly + a_executable);
282 else
283 make_t(pproc, t__invalid);
284 return 1;
285 }
286 check_proc(*pdval);
287 *pproc = *pdval;
288 return 0;
289 }
290
291 /* Get a matrix from a dictionary. */
292 int
dict_matrix_param(const gs_memory_t * mem,const ref * pdict,const char * kstr,gs_matrix * pmat)293 dict_matrix_param(const gs_memory_t *mem, const ref * pdict, const char *kstr, gs_matrix * pmat)
294 {
295 ref *pdval;
296
297 if (pdict == 0 || dict_find_string(pdict, kstr, &pdval) <= 0)
298 return_error(e_typecheck);
299 return read_matrix(mem, pdval, pmat);
300 }
301
302 /* Get a UniqueID or XUID from a dictionary. */
303 /* Return 0 if UniqueID, 1 if XUID, <0 if error. */
304 /* If there is no uid, return default. */
305 int
dict_uid_param(const ref * pdict,gs_uid * puid,int defaultval,gs_memory_t * mem,const i_ctx_t * i_ctx_p)306 dict_uid_param(const ref * pdict, gs_uid * puid, int defaultval,
307 gs_memory_t * mem, const i_ctx_t *i_ctx_p)
308 {
309 ref *puniqueid;
310
311 if (pdict == 0) {
312 uid_set_invalid(puid);
313 return defaultval;
314 }
315 /* In a Level 2 environment, check for XUID first. */
316 if (level2_enabled &&
317 dict_find_string(pdict, "XUID", &puniqueid) > 0
318 ) {
319 long *xvalues;
320 uint size, i;
321
322 if (!r_has_type(puniqueid, t_array))
323 return_error(e_typecheck);
324 size = r_size(puniqueid);
325 if (size == 0)
326 return_error(e_rangecheck);
327 xvalues = (long *)gs_alloc_byte_array(mem, size, sizeof(long),
328 "get XUID");
329
330 if (xvalues == 0)
331 return_error(e_VMerror);
332 /* Get the values from the XUID array. */
333 for (i = 0; i < size; i++) {
334 const ref *pvalue = puniqueid->value.const_refs + i;
335
336 if (!r_has_type(pvalue, t_integer)) {
337 gs_free_object(mem, xvalues, "get XUID");
338 return_error(e_typecheck);
339 }
340 xvalues[i] = pvalue->value.intval;
341 }
342 uid_set_XUID(puid, xvalues, size);
343 return 1;
344 }
345 /* If no UniqueID entry, set the UID to invalid, */
346 /* because UniqueID need not be present in all fonts, */
347 /* and if it is, the legal range is 0 to 2^24-1. */
348 if (dict_find_string(pdict, "UniqueID", &puniqueid) <= 0) {
349 uid_set_invalid(puid);
350 return defaultval;
351 } else {
352 if (!r_has_type(puniqueid, t_integer) ||
353 puniqueid->value.intval < 0 ||
354 puniqueid->value.intval > 0xffffffL
355 )
356 return_error(e_rangecheck);
357 /* Apparently fonts created by Fontographer often have */
358 /* a UniqueID of 0, contrary to Adobe's specifications. */
359 /* Treat 0 as equivalent to -1 (no UniqueID). */
360 if (puniqueid->value.intval == 0) {
361 uid_set_invalid(puid);
362 return defaultval;
363 } else
364 uid_set_UniqueID(puid, puniqueid->value.intval);
365 }
366 return 0;
367 }
368
369 /* Check that a UID in a dictionary is equal to an existing, valid UID. */
370 bool
dict_check_uid_param(const ref * pdict,const gs_uid * puid)371 dict_check_uid_param(const ref * pdict, const gs_uid * puid)
372 {
373 ref *puniqueid;
374
375 if (uid_is_XUID(puid)) {
376 uint size = uid_XUID_size(puid);
377 uint i;
378
379 if (dict_find_string(pdict, "XUID", &puniqueid) <= 0)
380 return false;
381 if (!r_has_type(puniqueid, t_array) ||
382 r_size(puniqueid) != size
383 )
384 return false;
385 for (i = 0; i < size; i++) {
386 const ref *pvalue = puniqueid->value.const_refs + i;
387
388 if (!r_has_type(pvalue, t_integer))
389 return false;
390 if (pvalue->value.intval != uid_XUID_values(puid)[i])
391 return false;
392 }
393 return true;
394 } else {
395 if (dict_find_string(pdict, "UniqueID", &puniqueid) <= 0)
396 return false;
397 return (r_has_type(puniqueid, t_integer) &&
398 puniqueid->value.intval == puid->id);
399 }
400 }
401