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 /* Implementation of FunctionType 4 (PostScript Calculator) Functions */
18 #include "math_.h"
19 #include "memory_.h"
20 #include "gx.h"
21 #include "gserrors.h"
22 #include "gsdsrc.h"
23 #include "gsfunc4.h"
24 #include "gxfarith.h"
25 #include "gxfunc.h"
26 #include "stream.h"
27 #include "strimpl.h"
28 #include "sfilter.h" /* for SubFileDecode */
29 #include "spprint.h"
30 #include "stream.h"
31
32 typedef struct gs_function_PtCr_s {
33 gs_function_head_t head;
34 gs_function_PtCr_params_t params;
35 /* Define a bogus DataSource for get_function_info. */
36 gs_data_source_t data_source;
37 } gs_function_PtCr_t;
38
39 /* GC descriptor */
40 private_st_function_PtCr();
41
42 /* Define the maximum stack depth. */
43 #define MAX_VSTACK 256 /* Max 100 is enough per PDF spec, but we use this
44 * for DeviceN handling. Must be at least as large
45 * as the number of components
46 */
47
48 /* Define the structure of values on the stack. */
49 typedef enum {
50 CVT_NONE = 0, /* empty stack slot */
51 CVT_BOOL,
52 CVT_INT,
53 CVT_FLOAT
54 } calc_value_type_t;
55 typedef struct calc_value_s {
56 calc_value_type_t type;
57 union {
58 int i; /* also used for Boolean */
59 float f;
60 } value;
61 } calc_value_t;
62
63 /* Store a float. */
64 static inline void
store_float(calc_value_t * vsp,double f)65 store_float(calc_value_t *vsp, double f)
66 {
67 vsp->value.f = f;
68 vsp->type = CVT_FLOAT;
69 }
70
71 /*
72 * Define extended opcodes with typed operands. We use the original
73 * opcodes for the floating-point case.
74 */
75 typedef enum {
76
77 /* Typed variants */
78
79 PtCr_abs_int = PtCr_NUM_OPCODES,
80 PtCr_add_int,
81 PtCr_mul_int,
82 PtCr_neg_int,
83 PtCr_not_bool, /* default is int */
84 PtCr_sub_int,
85 PtCr_eq_int,
86 PtCr_ge_int,
87 PtCr_gt_int,
88 PtCr_le_int,
89 PtCr_lt_int,
90 PtCr_ne_int,
91
92 /* Coerce and re-dispatch */
93
94 PtCr_int_to_float,
95 PtCr_2nd_int_to_float,
96 PtCr_int2_to_float,
97
98 /* Miscellaneous */
99
100 PtCr_no_op,
101 PtCr_typecheck
102
103 } gs_PtCr_typed_opcode_t;
104
105 /* Evaluate a PostScript Calculator function. */
106 static int
fn_PtCr_evaluate(const gs_function_t * pfn_common,const float * in,float * out)107 fn_PtCr_evaluate(const gs_function_t *pfn_common, const float *in, float *out)
108 {
109 const gs_function_PtCr_t *pfn = (const gs_function_PtCr_t *)pfn_common;
110 calc_value_t vstack_buf[2 + MAX_VSTACK + 1];
111 calc_value_t *vstack = &vstack_buf[1];
112 calc_value_t *vsp = vstack + pfn->params.m;
113 const byte *p = pfn->params.ops.data;
114 int repeat_count[MAX_PSC_FUNCTION_NESTING];
115 int repeat_proc_size[MAX_PSC_FUNCTION_NESTING];
116 int repeat_nesting_level = -1;
117 int i;
118
119 /*
120 * Define the table for mapping explicit opcodes to typed opcodes.
121 * We index this table with the opcode and the types of the top 2
122 * values on the stack.
123 */
124 static const struct op_defn_s {
125 byte opcode[16]; /* 4 * type[-1] + type[0] */
126 } op_defn_table[] = {
127 /* Keep this consistent with opcodes in gsfunc4.h! */
128
129 #define O4(op) op,op,op,op
130 #define E PtCr_typecheck
131 #define E4 O4(E)
132 #define N PtCr_no_op
133 /* 0-operand operators */
134 #define OP_NONE(op)\
135 {{O4(op), O4(op), O4(op), O4(op)}}
136 /* 1-operand operators */
137 #define OP1(b, i, f)\
138 {{E,b,i,f, E,b,i,f, E,b,i,f, E,b,i,f}}
139 #define OP_NUM1(i, f)\
140 OP1(E, i, f)
141 #define OP_MATH1(f)\
142 OP1(E, PtCr_int_to_float, f)
143 #define OP_ANY1(op)\
144 OP1(op, op, op)
145 /* 2-operand operators */
146 #define OP_NUM2(i, f)\
147 {{E4, E4, E,E,i,PtCr_2nd_int_to_float, E,E,PtCr_int_to_float,f}}
148 #define OP_INT_BOOL2(i)\
149 {{E4, E,i,i,E, E,i,i,E, E4}}
150 #define OP_MATH2(f)\
151 {{E4, E4, E,E,PtCr_int2_to_float,PtCr_2nd_int_to_float,\
152 E,E,PtCr_int_to_float,f}}
153 #define OP_INT2(i)\
154 {{E4, E4, E,E,i,E, E4}}
155 #define OP_REL2(i, f)\
156 {{E4, E,i,E,E, E,E,i,PtCr_2nd_int_to_float, E,E,PtCr_int_to_float,f}}
157 #define OP_ANY2(op)\
158 {{E4, E,op,op,op, E,op,op,op, E,op,op,op}}
159
160 /* Arithmetic operators */
161
162 OP_NUM1(PtCr_abs_int, PtCr_abs), /* abs */
163 OP_NUM2(PtCr_add_int, PtCr_add), /* add */
164 OP_INT_BOOL2(PtCr_and), /* and */
165 OP_MATH2(PtCr_atan), /* atan */
166 OP_INT2(PtCr_bitshift), /* bitshift */
167 OP_NUM1(N, PtCr_ceiling), /* ceiling */
168 OP_MATH1(PtCr_cos), /* cos */
169 OP_NUM1(N, PtCr_cvi), /* cvi */
170 OP_NUM1(PtCr_int_to_float, N), /* cvr */
171 OP_MATH2(PtCr_div), /* div */
172 OP_MATH2(PtCr_exp), /* exp */
173 OP_NUM1(N, PtCr_floor), /* floor */
174 OP_INT2(PtCr_idiv), /* idiv */
175 OP_MATH1(PtCr_ln), /* ln */
176 OP_MATH1(PtCr_log), /* log */
177 OP_INT2(PtCr_mod), /* mod */
178 OP_NUM2(PtCr_mul_int, PtCr_mul), /* mul */
179 OP_NUM1(PtCr_neg_int, PtCr_neg), /* neg */
180 OP1(PtCr_not, PtCr_not, E), /* not */
181 OP_INT_BOOL2(PtCr_or), /* or */
182 OP_NUM1(N, PtCr_round), /* round */
183 OP_MATH1(PtCr_sin), /* sin */
184 OP_MATH1(PtCr_sqrt), /* sqrt */
185 OP_NUM2(PtCr_sub_int, PtCr_sub), /* sub */
186 OP_NUM1(N, PtCr_truncate), /* truncate */
187 OP_INT_BOOL2(PtCr_xor), /* xor */
188
189 /* Comparison operators */
190
191 OP_REL2(PtCr_eq_int, PtCr_eq), /* eq */
192 OP_NUM2(PtCr_ge_int, PtCr_ge), /* ge */
193 OP_NUM2(PtCr_gt_int, PtCr_gt), /* gt */
194 OP_NUM2(PtCr_le_int, PtCr_le), /* le */
195 OP_NUM2(PtCr_lt_int, PtCr_lt), /* lt */
196 OP_REL2(PtCr_ne_int, PtCr_ne), /* ne */
197
198 /* Stack operators */
199
200 OP1(E, PtCr_copy, E), /* copy */
201 OP_ANY1(PtCr_dup), /* dup */
202 OP_ANY2(PtCr_exch), /* exch */
203 OP1(E, PtCr_index, E), /* index */
204 OP_ANY1(PtCr_pop), /* pop */
205 OP_INT2(PtCr_roll), /* roll */
206
207 /* Constants */
208
209 OP_NONE(PtCr_byte), /* byte */
210 OP_NONE(PtCr_int), /* int */
211 OP_NONE(PtCr_float), /* float */
212 OP_NONE(PtCr_true), /* true */
213 OP_NONE(PtCr_false), /* false */
214
215 /* Special */
216
217 OP1(PtCr_if, E, E), /* if */
218 OP_NONE(PtCr_else), /* else */
219 OP_NONE(PtCr_return), /* return */
220 OP1(E, PtCr_repeat, E), /* repeat */
221 OP_NONE(PtCr_repeat_end) /* repeat_end */
222 };
223
224 memset(repeat_count, 0x00, MAX_PSC_FUNCTION_NESTING * sizeof(int));
225 memset(repeat_proc_size, 0x00, MAX_PSC_FUNCTION_NESTING * sizeof(int));
226
227 vstack[-1].type = CVT_NONE; /* for type dispatch in empty stack case */
228 vstack[0].type = CVT_NONE; /* catch underflow */
229 for (i = 0; i < pfn->params.m; ++i)
230 store_float(&vstack[i + 1], in[i]);
231
232 for (; ; ) {
233 int code, n;
234
235 sw:
236 switch (op_defn_table[*p++].opcode[(vsp[-1].type << 2) + vsp->type]) {
237
238 /* Miscellaneous */
239
240 case PtCr_no_op:
241 continue;
242 case PtCr_typecheck:
243 return_error(gs_error_typecheck);
244
245 /* Coerce and re-dispatch */
246
247 case PtCr_int_to_float:
248 store_float(vsp, (double)vsp->value.i);
249 --p; goto sw;
250 case PtCr_int2_to_float:
251 store_float(vsp, (double)vsp->value.i);
252 /* fall through */
253 case PtCr_2nd_int_to_float:
254 store_float(vsp - 1, (double)vsp[-1].value.i);
255 --p; goto sw;
256
257 /* Arithmetic operators */
258
259 case PtCr_abs_int:
260 if (vsp->value.i < 0)
261 goto neg_int;
262 continue;
263 case PtCr_abs:
264 vsp->value.f = fabs(vsp->value.f);
265 continue;
266 case PtCr_add_int: {
267 int int1 = vsp[-1].value.i, int2 = vsp->value.i;
268
269 if ((int1 ^ int2) >= 0 && ((int1 + int2) ^ int1) < 0)
270 store_float(vsp - 1, (double)int1 + int2);
271 else
272 vsp[-1].value.i = int1 + int2;
273 --vsp; continue;
274 }
275 case PtCr_add:
276 vsp[-1].value.f += vsp->value.f;
277 --vsp; continue;
278 case PtCr_and:
279 vsp[-1].value.i &= vsp->value.i;
280 --vsp; continue;
281 case PtCr_atan: {
282 double result;
283
284 code = gs_atan2_degrees(vsp[-1].value.f, vsp->value.f,
285 &result);
286 if (code < 0)
287 return code;
288 vsp[-1].value.f = result;
289 --vsp; continue;
290 }
291 case PtCr_bitshift:
292 #define MAX_SHIFT (ARCH_SIZEOF_INT * 8 - 1)
293 if (vsp->value.i < -MAX_SHIFT || vsp->value.i > MAX_SHIFT)
294 vsp[-1].value.i = 0;
295 #undef MAX_SHIFT
296 else if ((n = vsp->value.i) < 0)
297 vsp[-1].value.i = ((uint)(vsp[-1].value.i)) >> -n;
298 else
299 vsp[-1].value.i <<= n;
300 --vsp; continue;
301 case PtCr_ceiling:
302 vsp->value.f = ceil(vsp->value.f);
303 continue;
304 case PtCr_cos:
305 vsp->value.f = gs_cos_degrees(vsp->value.f);
306 continue;
307 case PtCr_cvi:
308 {
309 /* Strictly speaking assigning one element of union
310 * to another, overlapping element of a different size is
311 * undefined behavior, hence assign to an intermediate variable
312 */
313 int int1 = (int)(vsp->value.f);
314 vsp->value.i = int1;
315 vsp->type = CVT_INT;
316 continue;
317 }
318 case PtCr_cvr:
319 continue; /* prepare handled it */
320 case PtCr_div:
321 if (vsp->value.f == 0)
322 return_error(gs_error_undefinedresult);
323 vsp[-1].value.f /= vsp->value.f;
324 --vsp; continue;
325 case PtCr_exp:
326 vsp[-1].value.f = pow(vsp[-1].value.f, vsp->value.f);
327 --vsp; continue;
328 case PtCr_floor:
329 vsp->value.f = floor(vsp->value.f);
330 continue;
331 case PtCr_idiv:
332 if (vsp->value.i == 0)
333 return_error(gs_error_undefinedresult);
334 if ((vsp[-1].value.i /= vsp->value.i) == min_int &&
335 vsp->value.i == -1) /* anomalous boundary case, fail */
336 return_error(gs_error_rangecheck);
337 --vsp; continue;
338 case PtCr_ln:
339 vsp->value.f = log(vsp->value.f);
340 continue;
341 case PtCr_log:
342 vsp->value.f = log10(vsp->value.f);
343 continue;
344 case PtCr_mod:
345 if (vsp->value.i == 0)
346 return_error(gs_error_undefinedresult);
347 vsp[-1].value.i %= vsp->value.i;
348 --vsp; continue;
349 case PtCr_mul_int: {
350 /* We don't bother to optimize this. */
351 double prod = (double)vsp[-1].value.i * vsp->value.i;
352
353 if (prod < min_int || prod > max_int)
354 store_float(vsp - 1, prod);
355 else
356 vsp[-1].value.i = (int)prod;
357 --vsp; continue;
358 }
359 case PtCr_mul:
360 vsp[-1].value.f *= vsp->value.f;
361 --vsp; continue;
362 case PtCr_neg_int:
363 neg_int:
364 if (vsp->value.i == min_int)
365 store_float(vsp, (double)vsp->value.i); /* =self negated */
366 else
367 vsp->value.i = -vsp->value.i;
368 continue;
369 case PtCr_neg:
370 vsp->value.f = -vsp->value.f;
371 continue;
372 case PtCr_not_bool:
373 vsp->value.i = !vsp->value.i;
374 continue;
375 case PtCr_not:
376 vsp->value.i = ~vsp->value.i;
377 continue;
378 case PtCr_or:
379 vsp[-1].value.i |= vsp->value.i;
380 --vsp; continue;
381 case PtCr_round:
382 vsp->value.f = floor(vsp->value.f + 0.5);
383 continue;
384 case PtCr_sin:
385 vsp->value.f = gs_sin_degrees(vsp->value.f);
386 continue;
387 case PtCr_sqrt:
388 vsp->value.f = sqrt(vsp->value.f);
389 continue;
390 case PtCr_sub_int: {
391 int int1 = vsp[-1].value.i, int2 = vsp->value.i;
392
393 if ((int1 ^ int2) < 0 && ((int1 - int2) ^ int1) >= 0)
394 store_float(vsp - 1, (double)int1 - int2);
395 else
396 vsp[-1].value.i = int1 - int2;
397 --vsp; continue;
398 }
399 case PtCr_sub:
400 vsp[-1].value.f -= vsp->value.f;
401 --vsp; continue;
402 case PtCr_truncate:
403 vsp->value.f = (vsp->value.f < 0 ? ceil(vsp->value.f) :
404 floor(vsp->value.f));
405 continue;
406 case PtCr_xor:
407 vsp[-1].value.i ^= vsp->value.i;
408 --vsp; continue;
409
410 /* Boolean operators */
411
412 #define DO_REL(rel, m)\
413 vsp[-1].value.i = vsp[-1].value.m rel vsp->value.m
414
415 case PtCr_eq_int:
416 DO_REL(==, i);
417 goto rel;
418 case PtCr_eq:
419 DO_REL(==, f);
420 rel:
421 vsp[-1].type = CVT_BOOL;
422 --vsp; continue;
423 case PtCr_ge_int:
424 DO_REL(>=, i);
425 goto rel;
426 case PtCr_ge:
427 DO_REL(>=, f);
428 goto rel;
429 case PtCr_gt_int:
430 DO_REL(>, i);
431 goto rel;
432 case PtCr_gt:
433 DO_REL(>, f);
434 goto rel;
435 case PtCr_le_int:
436 DO_REL(<=, i);
437 goto rel;
438 case PtCr_le:
439 DO_REL(<=, f);
440 goto rel;
441 case PtCr_lt_int:
442 DO_REL(<, i);
443 goto rel;
444 case PtCr_lt:
445 DO_REL(<, f);
446 goto rel;
447 case PtCr_ne_int:
448 DO_REL(!=, i);
449 goto rel;
450 case PtCr_ne:
451 DO_REL(!=, f);
452 goto rel;
453
454 #undef DO_REL
455
456 /* Stack operators */
457
458 case PtCr_copy:
459 i = vsp->value.i;
460 n = vsp - vstack;
461 if (i < 0 || i >= n)
462 return_error(gs_error_rangecheck);
463 if (i > MAX_VSTACK - (n - 1))
464 return_error(gs_error_limitcheck);
465 memcpy(vsp, vsp - i, i * sizeof(*vsp));
466 vsp += i - 1;
467 continue;
468 case PtCr_dup:
469 vsp[1] = *vsp;
470 goto push;
471 case PtCr_exch:
472 vstack[MAX_VSTACK] = *vsp;
473 *vsp = vsp[-1];
474 vsp[-1] = vstack[MAX_VSTACK];
475 continue;
476 case PtCr_index:
477 i = vsp->value.i;
478 if (i < 0 || i >= vsp - vstack - 1)
479 return_error(gs_error_rangecheck);
480 *vsp = vsp[-i - 1];
481 continue;
482 case PtCr_pop:
483 --vsp;
484 continue;
485 case PtCr_roll:
486 n = vsp[-1].value.i;
487 i = vsp->value.i;
488 if (n < 0 || n > vsp - vstack - 2)
489 return_error(gs_error_rangecheck);
490 /* We don't bother to do this efficiently. */
491 for (; i > 0; i--) {
492 memmove(vsp - n, vsp - (n + 1), n * sizeof(*vsp));
493 vsp[-(n + 1)] = vsp[-1];
494 }
495 for (; i < 0; i++) {
496 vsp[-1] = vsp[-(n + 1)];
497 memmove(vsp - (n + 1), vsp - n, n * sizeof(*vsp));
498 }
499 vsp -= 2;
500 continue;
501
502 /* Constants */
503
504 case PtCr_byte:
505 vsp[1].value.i = *p++, vsp[1].type = CVT_INT;
506 goto push;
507 case PtCr_int /* native */:
508 memcpy(&vsp[1].value.i, p, sizeof(int));
509 vsp[1].type = CVT_INT;
510 p += sizeof(int);
511 goto push;
512 case PtCr_float /* native */:
513 memcpy(&vsp[1].value.f, p, sizeof(float));
514 vsp[1].type = CVT_FLOAT;
515 p += sizeof(float);
516 goto push;
517 case PtCr_true:
518 vsp[1].value.i = true, vsp[1].type = CVT_BOOL;
519 goto push;
520 case PtCr_false:
521 vsp[1].value.i = false, vsp[1].type = CVT_BOOL;
522 push:
523 if (vsp == &vstack[MAX_VSTACK])
524 return_error(gs_error_limitcheck);
525 ++vsp;
526 continue;
527
528 /* Special */
529
530 case PtCr_if:
531 if ((vsp--)->value.i) { /* value is true, execute body */
532 p += 2;
533 continue;
534 }
535 /* falls through */
536 case PtCr_else:
537 p += 2 + (p[0] << 8) + p[1]; /* skip the past body */
538 continue;
539 case PtCr_return:
540 goto fin;
541 case PtCr_repeat:
542 repeat_nesting_level++;
543 repeat_count[repeat_nesting_level] = vsp->value.i;
544 repeat_proc_size[repeat_nesting_level] = 1 + (p[0] << 8) + p[1]; /* body size */
545 --vsp; /* pop the counter */
546 p += 3 + (p[0] <<8) + p[1]; /* advance just past the repeat_end */
547 /* falls through */
548 case PtCr_repeat_end:
549 if (repeat_nesting_level < 0)
550 return_error(gs_error_rangecheck);
551
552 if ((repeat_count[repeat_nesting_level])-- <= 0)
553 repeat_nesting_level--;
554 else
555 p -= repeat_proc_size[repeat_nesting_level];
556 continue;
557 }
558 }
559 fin:
560
561 if (vsp != vstack + pfn->params.n)
562 return_error(gs_error_rangecheck);
563 for (i = 0; i < pfn->params.n; ++i) {
564 switch (vstack[i + 1].type) {
565 case CVT_INT:
566 out[i] = (float)vstack[i + 1].value.i;
567 break;
568 case CVT_FLOAT:
569 out[i] = vstack[i + 1].value.f;
570 break;
571 default:
572 return_error(gs_error_typecheck);
573 }
574 }
575 return 0;
576 }
577
578 /* Test whether a PostScript Calculator function is monotonic. */
579 static int
fn_PtCr_is_monotonic(const gs_function_t * pfn_common,const float * lower,const float * upper,uint * mask)580 fn_PtCr_is_monotonic(const gs_function_t * pfn_common,
581 const float *lower, const float *upper, uint *mask)
582 {
583 /*
584 * No reasonable way to tell. Eventually we should check for
585 * functions consisting of only stack-manipulating operations,
586 * since these may be common for DeviceN color spaces and *are*
587 * monotonic.
588 */
589 *mask = 0x49249249;
590 return 0;
591 }
592
593 /* Write the function definition in symbolic form on a stream. */
594 static int
calc_put_ops(stream * s,const byte * ops,uint size)595 calc_put_ops(stream *s, const byte *ops, uint size)
596 {
597 const byte *p;
598
599 spputc(s, '{');
600 for (p = ops; p < ops + size; )
601 switch (*p++) {
602 case PtCr_byte:
603 pprintd1(s, "%d ", *p++);
604 break;
605 case PtCr_int: {
606 int i;
607
608 memcpy(&i, p, sizeof(int));
609 pprintd1(s, "%d ", i);
610 p += sizeof(int);
611 break;
612 }
613 case PtCr_float: {
614 float f;
615
616 memcpy(&f, p, sizeof(float));
617 pprintg1(s, "%g ", f);
618 p += sizeof(float);
619 break;
620 }
621 case PtCr_true:
622 stream_puts(s, "true ");
623 break;
624 case PtCr_false:
625 stream_puts(s, "false ");
626 break;
627 case PtCr_if: {
628 int skip = (p[0] << 8) + p[1];
629 int code;
630
631 code = calc_put_ops(s, p += 2, skip);
632 p += skip;
633 if (code < 0)
634 return code;
635 if (code > 0) { /* else */
636 skip = (p[-2] << 8) + p[-1];
637 code = calc_put_ops(s, p, skip);
638 p += skip;
639 if (code < 0)
640 return code;
641 stream_puts(s, " ifelse ");
642 } else
643 stream_puts(s, " if ");
644 break;
645 }
646 case PtCr_else:
647 if (p != ops + size - 2)
648 return_error(gs_error_rangecheck);
649 spputc(s, '}');
650 return 1;
651 /*case PtCr_return:*/ /* not possible */
652 case PtCr_repeat: /* We shouldn't encounter this, but just in case */
653 case PtCr_repeat_end:
654 return_error(gs_error_rangecheck);
655 default: { /* must be < PtCr_NUM_OPS */
656 static const char *const op_names[] = {
657 /* Keep this consistent with opcodes in gsfunc4.h! */
658 "abs", "add", "and", "atan", "bitshift",
659 "ceiling", "cos", "cvi", "cvr", "div", "exp",
660 "floor", "idiv", "ln", "log", "mod", "mul",
661 "neg", "not", "or", "round", "sin", "sqrt", "sub",
662 "truncate", "xor",
663 "eq", "ge", "gt", "le", "lt", "ne",
664 "copy", "dup", "exch", "index", "pop", "roll"
665 };
666
667 pprints1(s, "%s ", op_names[p[-1]]);
668 }
669 }
670 spputc(s, '}');
671 return 0;
672 }
673 static int
calc_put(stream * s,const gs_function_PtCr_t * pfn)674 calc_put(stream *s, const gs_function_PtCr_t *pfn)
675 {
676 calc_put_ops(s, pfn->params.ops.data, pfn->params.ops.size - 1);
677 return 0;
678 }
679
680 /* Access the symbolic definition as a DataSource. */
681 static int
calc_access(const gs_data_source_t * psrc,ulong start,uint length,byte * buf,const byte ** ptr)682 calc_access(const gs_data_source_t *psrc, ulong start, uint length,
683 byte *buf, const byte **ptr)
684 {
685 const gs_function_PtCr_t *const pfn =
686 (const gs_function_PtCr_t *)
687 ((const char *)psrc - offset_of(gs_function_PtCr_t, data_source));
688 /*
689 * The caller wants a specific substring of the symbolic definition.
690 * Generate the entire definition, using a SubFileDecode filter (in an
691 * output pipeline!) to extract the substring. This is very
692 * inefficient, but this code is rarely used, and almost never actually
693 * has to break up the definition into pieces to fit in the caller's
694 * buffer.
695 */
696 stream_SFD_state st;
697 stream ds, bs;
698 byte dbuf[200]; /* arbitrary */
699 const stream_template *const templat = &s_SFD_template;
700
701 /* Set up the stream that writes into the buffer. */
702 s_init(&bs, NULL);
703 swrite_string(&bs, buf, length);
704 /* Set up the SubFileDecode stream. */
705 s_init(&ds, NULL);
706 s_init_state((stream_state *)&st, templat, NULL);
707 templat->set_defaults((stream_state *)&st);
708 st.skip_count = start;
709 s_init_filter(&ds, (stream_state *)&st, dbuf, sizeof(dbuf), &bs);
710 calc_put(&ds, pfn);
711 sclose(&ds);
712 if (ptr)
713 *ptr = buf;
714 return 0;
715 }
716
717 /* Return PostScript Calculator function information. */
718 static void
fn_PtCr_get_info(const gs_function_t * pfn_common,gs_function_info_t * pfi)719 fn_PtCr_get_info(const gs_function_t *pfn_common, gs_function_info_t *pfi)
720 {
721 const gs_function_PtCr_t *const pfn =
722 (const gs_function_PtCr_t *)pfn_common;
723
724 gs_function_get_info_default(pfn_common, pfi);
725 pfi->DataSource = &pfn->data_source;
726 {
727 stream s;
728
729 s_init(&s, NULL);
730 swrite_position_only(&s);
731 calc_put(&s, pfn);
732 pfi->data_size = stell(&s);
733 }
734 }
735
736 /* Make a scaled copy of a PostScript Calculator function. */
737 static int
fn_PtCr_make_scaled(const gs_function_PtCr_t * pfn,gs_function_PtCr_t ** ppsfn,const gs_range_t * pranges,gs_memory_t * mem)738 fn_PtCr_make_scaled(const gs_function_PtCr_t *pfn, gs_function_PtCr_t **ppsfn,
739 const gs_range_t *pranges, gs_memory_t *mem)
740 {
741 gs_function_PtCr_t *psfn =
742 gs_alloc_struct(mem, gs_function_PtCr_t, &st_function_PtCr,
743 "fn_PtCr_make_scaled");
744 /* We are adding {<int> 1 roll <float> mul <float> add} for each output. */
745 int n = pfn->params.n;
746 uint opsize = pfn->params.ops.size + (9 + 2 * sizeof(float)) * n;
747 byte *ops = gs_alloc_string(mem, opsize, "fn_PtCr_make_scaled(ops)");
748 byte *p;
749 int code, i;
750
751 if (psfn == 0 || ops == 0) {
752 gs_free_string(mem, ops, opsize, "fn_PtCr_make_scaled(ops)");
753 gs_free_object(mem, psfn, "fn_PtCr_make_scaled");
754 return_error(gs_error_VMerror);
755 }
756 psfn->params = pfn->params;
757 psfn->params.ops.data = ops;
758 psfn->params.ops.size = opsize;
759 psfn->data_source = pfn->data_source;
760 code = fn_common_scale((gs_function_t *)psfn, (const gs_function_t *)pfn,
761 pranges, mem);
762 if (code < 0) {
763 gs_function_free((gs_function_t *)psfn, true, mem);
764 return code;
765 }
766 memcpy(ops, pfn->params.ops.data, pfn->params.ops.size - 1); /* minus return */
767 p = ops + pfn->params.ops.size - 1;
768 for (i = n; --i >= 0; ) {
769 float base = pranges[i].rmin;
770 float factor = pranges[i].rmax - base;
771
772 if (factor != 1) {
773 p[0] = PtCr_float; memcpy(p + 1, &factor, sizeof(float));
774 p += 1 + sizeof(float);
775 *p++ = PtCr_mul;
776 }
777 if (base != 0) {
778 p[0] = PtCr_float; memcpy(p + 1, &base, sizeof(float));
779 p += 1 + sizeof(float);
780 *p++ = PtCr_add;
781 }
782 if (n != 1) {
783 p[0] = PtCr_byte; p[1] = (byte)n;
784 p[2] = PtCr_byte; p[3] = 1;
785 p[4] = PtCr_roll;
786 p += 5;
787 }
788 }
789 *p++ = PtCr_return;
790 psfn->params.ops.size = p - ops;
791 psfn->params.ops.data =
792 gs_resize_string(mem, ops, opsize, psfn->params.ops.size,
793 "fn_PtCr_make_scaled");
794 *ppsfn = psfn;
795 return 0;
796 }
797
798 /* Free the parameters of a PostScript Calculator function. */
799 void
gs_function_PtCr_free_params(gs_function_PtCr_params_t * params,gs_memory_t * mem)800 gs_function_PtCr_free_params(gs_function_PtCr_params_t * params, gs_memory_t * mem)
801 {
802 gs_free_const_string(mem, params->ops.data, params->ops.size, "ops");
803 params->ops.data = NULL;
804 params->ops.size = 0;
805 fn_common_free_params((gs_function_params_t *) params, mem);
806 }
807
808 /* Serialize. */
809 static int
gs_function_PtCr_serialize(const gs_function_t * pfn,stream * s)810 gs_function_PtCr_serialize(const gs_function_t * pfn, stream *s)
811 {
812 uint n;
813 const gs_function_PtCr_params_t * p = (const gs_function_PtCr_params_t *)&pfn->params;
814 int code = fn_common_serialize(pfn, s);
815
816 if (code < 0)
817 return code;
818 code = sputs(s, (const byte *)&p->ops.size, sizeof(p->ops.size), &n);
819 if (code < 0)
820 return code;
821 return sputs(s, p->ops.data, p->ops.size, &n);
822 }
823
824 /* Allocate and initialize a PostScript Calculator function. */
825 int
gs_function_PtCr_init(gs_function_t ** ppfn,const gs_function_PtCr_params_t * params,gs_memory_t * mem)826 gs_function_PtCr_init(gs_function_t ** ppfn,
827 const gs_function_PtCr_params_t * params, gs_memory_t * mem)
828 {
829 static const gs_function_head_t function_PtCr_head = {
830 function_type_PostScript_Calculator,
831 {
832 (fn_evaluate_proc_t) fn_PtCr_evaluate,
833 (fn_is_monotonic_proc_t) fn_PtCr_is_monotonic,
834 (fn_get_info_proc_t) fn_PtCr_get_info,
835 fn_common_get_params,
836 (fn_make_scaled_proc_t) fn_PtCr_make_scaled,
837 (fn_free_params_proc_t) gs_function_PtCr_free_params,
838 fn_common_free,
839 (fn_serialize_proc_t) gs_function_PtCr_serialize,
840 }
841 };
842 int code;
843
844 *ppfn = 0; /* in case of error */
845 code = fn_check_mnDR((const gs_function_params_t *)params,
846 params->m, params->n);
847 if (code < 0)
848 return code;
849 if (params->m > MAX_VSTACK || params->n > MAX_VSTACK)
850 return_error(gs_error_limitcheck);
851 /*
852 * Pre-validate the operation string to reduce evaluation overhead.
853 */
854 {
855 const byte *p = params->ops.data;
856
857 for (; *p != PtCr_return; ++p)
858 switch ((gs_PtCr_opcode_t)*p) {
859 case PtCr_byte:
860 ++p; break;
861 case PtCr_int:
862 p += sizeof(int); break;
863 case PtCr_float:
864 p += sizeof(float); break;
865 case PtCr_repeat:
866 case PtCr_if:
867 case PtCr_else:
868 p += 2;
869 case PtCr_repeat_end:
870 case PtCr_true:
871 case PtCr_false:
872 break;
873 default:
874 if (*p >= PtCr_NUM_OPS)
875 return_error(gs_error_rangecheck);
876 }
877 if (p != params->ops.data + params->ops.size - 1)
878 return_error(gs_error_rangecheck);
879 }
880 {
881 gs_function_PtCr_t *pfn =
882 gs_alloc_struct(mem, gs_function_PtCr_t, &st_function_PtCr,
883 "gs_function_PtCr_init");
884
885 if (pfn == 0)
886 return_error(gs_error_VMerror);
887 pfn->params = *params;
888 /*
889 * We claim to have a DataSource, in order to write the function
890 * definition in symbolic form for embedding in PDF files.
891 * ****** THIS IS A HACK. ******
892 */
893 data_source_init_string2(&pfn->data_source, NULL, 0);
894 pfn->data_source.access = calc_access;
895 pfn->head = function_PtCr_head;
896 *ppfn = (gs_function_t *) pfn;
897 }
898 return 0;
899 }
900