Coverage Report

Created: 2026-04-01 07:17

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ghostpdl/psi/zfunc4.c
Line
Count
Source
1
/* Copyright (C) 2001-2026 Artifex Software, Inc.
2
   All Rights Reserved.
3
4
   This software is provided AS-IS with no warranty, either express or
5
   implied.
6
7
   This software is distributed under license and may not be copied,
8
   modified or distributed except as expressly authorized under the terms
9
   of the license contained in the file LICENSE in this distribution.
10
11
   Refer to licensing information at http://www.artifex.com or contact
12
   Artifex Software, Inc.,  39 Mesa Street, Suite 108A, San Francisco,
13
   CA 94129, USA, for further information.
14
*/
15
16
17
/* PostScript language support for FunctionType 4 (PS Calculator) Functions */
18
#include "memory_.h"
19
#include "ghost.h"
20
#include "oper.h"
21
#include "opextern.h"
22
#include "gsfunc.h"
23
#include "gsfunc4.h"
24
#include "gsutil.h"
25
#include "idict.h"
26
#include "ifunc.h"
27
#include "iname.h"
28
#include "dstack.h"
29
#include "ialloc.h"
30
#include "gzstate.h"      /* these are needed to check device parameters */
31
#include "gsparam.h"      /* these are needed to check device parameters */
32
#include "zfunc.h"
33
#include "zcolor.h"
34
#include "gxdevsop.h"
35
36
/*
37
 * FunctionType 4 functions are not defined in the PostScript language.  We
38
 * provide support for them because they are needed for PDF 1.3.  In
39
 * addition to the standard FunctionType, Domain, and Range keys, they have
40
 * a Function key whose value is a procedure in a restricted subset of the
41
 * PostScript language.  Specifically, the procedure must (recursively)
42
 * contain only integer, real, Boolean, and procedure constants (only as
43
 * literal operands of if and and ifelse), and operators chosen from the set
44
 * given below.  Note that names other than true and false are not allowed:
45
 * the procedure must be 'bound'.
46
 *
47
 * The following list is taken directly from the PDF 1.3 documentation.
48
 */
49
#define XOP(zfn) int zfn(i_ctx_t *)
50
XOP(zabs); XOP(zand); XOP(zatan); XOP(zbitshift);
51
XOP(zceiling); XOP(zcos); XOP(zcvi); XOP(zcvr);
52
XOP(zdiv); XOP(zexp); XOP(zfloor); XOP(zidiv);
53
XOP(zln); XOP(zlog); XOP(zmod); XOP(zmul);
54
XOP(zneg); XOP(znot); XOP(zor); XOP(zround);
55
XOP(zsin); XOP(zsqrt); XOP(ztruncate); XOP(zxor);
56
XOP(zeq); XOP(zge); XOP(zgt); XOP(zle); XOP(zlt); XOP(zne);
57
XOP(z2copy);
58
#undef XOP
59
typedef struct calc_op_s {
60
    op_proc_t proc;
61
    gs_PtCr_opcode_t opcode;
62
} calc_op_t;
63
static const calc_op_t calc_ops[] = {
64
65
    /* Arithmetic operators */
66
67
    {zabs, PtCr_abs},
68
    {zadd, PtCr_add},
69
    {zand, PtCr_and},
70
    {zatan, PtCr_atan},
71
    {zbitshift, PtCr_bitshift},
72
    {zceiling, PtCr_ceiling},
73
    {zcos, PtCr_cos},
74
    {zcvi, PtCr_cvi},
75
    {zcvr, PtCr_cvr},
76
    {zdiv, PtCr_div},
77
    {zexp, PtCr_exp},
78
    {zfloor, PtCr_floor},
79
    {zidiv, PtCr_idiv},
80
    {zln, PtCr_ln},
81
    {zlog, PtCr_log},
82
    {zmod, PtCr_mod},
83
    {zmul, PtCr_mul},
84
    {zneg, PtCr_neg},
85
    {znot, PtCr_not},
86
    {zor, PtCr_or},
87
    {zround, PtCr_round},
88
    {zsin, PtCr_sin},
89
    {zsqrt, PtCr_sqrt},
90
    {zsub, PtCr_sub},
91
    {ztruncate, PtCr_truncate},
92
    {zxor, PtCr_xor},
93
94
    /* Comparison operators */
95
96
    {zeq, PtCr_eq},
97
    {zge, PtCr_ge},
98
    {zgt, PtCr_gt},
99
    {zle, PtCr_le},
100
    {zlt, PtCr_lt},
101
    {zne, PtCr_ne},
102
103
    /* Stack operators */
104
105
    {zcopy, PtCr_copy},
106
    {z2copy, PtCr_copy},
107
    {zdup, PtCr_dup},
108
    {zexch, PtCr_exch},
109
    {zindex, PtCr_index},
110
    {zpop, PtCr_pop},
111
    {zroll, PtCr_roll}
112
113
    /* Special operators */
114
115
    /*{zif, PtCr_if},*/
116
    /*{zifelse, PtCr_ifelse},*/
117
    /*{ztrue, PtCr_true},*/
118
    /*{zfalse, PtCr_false}*/
119
};
120
121
/* Fix up an if or ifelse forward reference. */
122
static int
123
psc_fixup(byte *p, byte *to)
124
0
{
125
0
    int skip = to - (p + 3);
126
127
0
    if (skip > 0xFFFF)
128
0
        return_error(gs_error_rangecheck);
129
130
0
    p[1] = (byte)(skip >> 8);
131
0
    p[2] = (byte)skip;
132
0
    return 0;
133
0
}
134
135
/* Check whether the ref is a given operator or resolves to it */
136
static bool
137
resolves_to_oper(i_ctx_t *i_ctx_p, const ref *pref, const op_proc_t proc)
138
0
{
139
0
    if (!r_has_attr(pref, a_executable))
140
0
        return false;
141
0
    if (r_btype(pref) == t_operator) {
142
0
        return pref->value.opproc == proc;
143
0
    } else if (r_btype(pref) == t_name) {
144
0
        ref * val;
145
0
        if (dict_find(systemdict, pref, &val) <= 0)
146
0
            return false;
147
0
        if (r_btype(val) != t_operator)
148
0
            return false;
149
0
        if (!r_has_attr(val, a_executable))
150
0
            return false;
151
0
        return val->value.opproc == proc;
152
0
    }
153
0
   else
154
0
      return false;
155
0
}
156
157
/* Store an int in the  buffer */
158
static int
159
21.0k
put_int(byte **p, int n) {
160
21.0k
   if (n == (byte)n) {
161
18.9k
       if (*p) {
162
18.9k
          (*p)[0] = PtCr_byte;
163
18.9k
          (*p)[1] = (byte)n;
164
18.9k
          *p += 2;
165
18.9k
       }
166
18.9k
       return 2;
167
18.9k
   } else {
168
2.06k
       if (*p) {
169
2.06k
          **p = PtCr_int;
170
2.06k
          memcpy(*p + 1, &n, sizeof(int));
171
2.06k
          *p += sizeof(int) + 1;
172
2.06k
       }
173
2.06k
       return (sizeof(int) + 1);
174
2.06k
   }
175
21.0k
}
176
177
/* Store a float in the  buffer */
178
static int
179
44.2k
put_float(byte **p, float n) {
180
44.2k
   if (*p) {
181
44.2k
      **p = PtCr_float;
182
44.2k
      memcpy(*p + 1, &n, sizeof(float));
183
44.2k
      *p += sizeof(float) + 1;
184
44.2k
   }
185
44.2k
   return (sizeof(float) + 1);
186
44.2k
}
187
188
/* Store an op code in the  buffer */
189
static int
190
0
put_op(byte **p, byte op) {
191
0
   if (*p)
192
0
      *(*p)++ = op;
193
0
   return 1;
194
0
}
195
196
/*
197
 * Check a calculator function for validity, optionally storing its encoded
198
 * representation and add the size of the encoded representation to *psize.
199
 * Note that we arbitrarily limit the depth of procedure nesting.  pref is
200
 * known to be a procedure.
201
 */
202
static int
203
check_psc_function(i_ctx_t *i_ctx_p, const ref *pref, int depth, byte *ops, uint *psize, bool AllowRepeat)
204
13.6k
{
205
13.6k
    int code;
206
13.6k
    uint i, j;
207
13.6k
    uint size = r_size(pref);
208
13.6k
    byte *p;
209
210
13.6k
    if (size == 2 && depth == 0) {
211
        /* Bug 690986. Recognize and replace Corel tint transform function.
212
           { tint_params CorelTintTransformFunction }
213
214
           Where tint_params resolves to an arrey like:
215
             [ 1.0 0.0 0.0 0.0
216
               0.0 1.0 0.0 0.0
217
               0.0 0.0 1.0 0.0
218
               0.0 0.0 0.0 1.0
219
               0.2 0.81 0.76 0.61
220
            ]
221
           And CorelTintTransformFunction is:
222
            { /colorantSpecArray exch def
223
              /nColorants colorantSpecArray length 4 idiv def
224
              /inColor nColorants 1 add 1 roll nColorants array astore def
225
              /outColor 4 array def
226
              0 1 3 {
227
                /nOutInk exch def
228
                1
229
                0 1 nColorants 1 sub {
230
                  dup inColor exch get
231
                  exch 4 mul nOutInk add colorantSpecArray exch get mul
232
                  1 exch sub mul
233
                } for
234
                1 exch sub
235
                outColor nOutInk 3 -1 roll put
236
              } for
237
              outColor aload pop
238
            }
239
        */
240
15
        ref r_tp, r_cttf; /* original references */
241
15
        ref n_tp, n_cttf; /* names */
242
15
        ref *v_tp, *v_cttf; /* values */
243
15
        int sz;
244
245
15
        p = ops;
246
15
        sz = *psize;
247
15
        if(array_get(imemory, pref, 0, &r_tp) < 0)
248
0
            goto idiom_failed;
249
15
        if (array_get(imemory, pref, 1, &r_cttf) < 0)
250
0
            goto idiom_failed;
251
15
        if (r_has_type(&r_tp, t_name) && r_has_type(&r_cttf, t_name)) {
252
0
            if ((code = name_enter_string(imemory, "tint_params", &n_tp)) < 0)
253
0
                return code;
254
0
            if (r_tp.value.pname == n_tp.value.pname) {
255
0
                if ((code = name_enter_string(imemory, "CorelTintTransformFunction", &n_cttf)) < 0)
256
0
                    return code;
257
0
                if (r_cttf.value.pname == n_cttf.value.pname) {
258
0
                    v_tp   = dict_find_name(&n_tp);
259
0
                    v_cttf = dict_find_name(&n_cttf);
260
0
                    if (v_tp && v_cttf && r_is_array(v_tp) && r_is_array(v_cttf)) {
261
0
                        uint n_elem = r_size(v_tp);
262
263
0
                        if ((n_elem & 3) == 0 && r_size(v_cttf) == 31) {
264
                            /* Enough testing, idiom recognition tests less. */
265
0
                            uint n_col = n_elem/4;
266
267
0
                            for (i = 0; i < 4; i ++) {
268
0
                                ref v;
269
0
                                float fv;
270
0
                                bool first = true;
271
272
0
                                for (j = 0; j < n_col; j++) {
273
0
                                    if (array_get(imemory, v_tp, j*4 + i, &v) < 0)
274
0
                                        goto idiom_failed;
275
0
                                    if (r_type(&v) == t_integer)
276
0
                                        fv = (float)v.value.intval;
277
0
                                    else if (r_type(&v) == t_real)
278
0
                                        fv = v.value.realval;
279
0
                                    else
280
0
                                        goto idiom_failed;
281
282
0
                                    if (fv != 0.) {
283
                                        /* Ensure we can't overflow max_uint, Worst case is 3 x put_int + put_float + 4 x put_op */
284
0
                                        if (sz > max_uint - ((3 * (sizeof(int) + 1)) + (sizeof(float) + 1) + 4))
285
0
                                            return_error(gs_error_VMerror);
286
287
0
                                        if (first)
288
0
                                            sz += put_int(&p, 1);
289
0
                                        sz += put_int(&p, 1);
290
0
                                        sz += put_int(&p, n_col + 1 - j + i + !first);
291
0
                                        sz += put_op(&p, PtCr_index);
292
0
                                        if (fv != 1.) {
293
0
                                            sz += put_float(&p, fv);
294
0
                                            sz += put_op(&p, PtCr_mul);
295
0
                                        }
296
0
                                        sz += put_op(&p, PtCr_sub);
297
0
                                        if (first)
298
0
                                            first = false;
299
0
                                        else
300
0
                                            sz += put_op(&p, PtCr_mul);
301
0
                                    }
302
0
                                }
303
                                /* Ensure we can't overflow max_uint */
304
0
                                if (sz > max_uint - (sizeof(int) + 1))
305
0
                                    return_error(gs_error_VMerror);
306
0
                                if (first)
307
0
                                    sz += put_int(&p, 0);
308
0
                                else
309
0
                                    sz += put_op(&p, PtCr_sub);
310
0
                            }
311
                            /* Ensure we can't overflow max_uint; required size is 2 x put_int + put_op + n_col x put_op */
312
0
                            if (sz > max_uint - ((2 * (sizeof(int) + 1)) + n_col + 1))
313
0
                                return_error(gs_error_VMerror);
314
                            /* n_col+4 4 roll pop ... pop  */
315
0
                            sz += put_int(&p, n_col + 4);
316
0
                            sz += put_int(&p, 4);
317
0
                            sz += put_op(&p, PtCr_roll);
318
0
                            for (j = 0; j < n_col; j++)
319
0
                                sz += put_op(&p, PtCr_pop);
320
0
                            *psize = sz;
321
0
                            return 0;
322
0
                        }
323
0
                    }
324
0
                }
325
0
            }
326
0
        }
327
15
    }
328
13.6k
  idiom_failed:;
329
93.6k
    for (i = 0; i < size; ++i) {
330
80.2k
        byte no_ops[1 + max(sizeof(int), sizeof(float))];
331
80.2k
        ref elt, elt2, elt3;
332
80.2k
        ref * delp;
333
334
80.2k
        p = (ops ? ops + *psize : no_ops);
335
80.2k
        array_get(imemory, pref, i, &elt);
336
80.2k
        switch (r_btype(&elt)) {
337
21.0k
        case t_integer:
338
            /* Ensure we can't overflow max_uint */
339
21.0k
            if (*psize > max_uint - (sizeof(int) + 1))
340
0
                return_error(gs_error_VMerror);
341
21.0k
            *psize += put_int(&p, elt.value.intval);
342
21.0k
            break;
343
44.2k
        case t_real:
344
            /* Ensure we can't overflow max_uint */
345
44.2k
            if (*psize > max_uint - (sizeof(float) + 1))
346
0
                return_error(gs_error_VMerror);
347
44.2k
            *psize += put_float(&p, elt.value.realval);
348
44.2k
            break;
349
0
        case t_boolean:
350
            /* Ensure we can't overflow max_uint */
351
0
            if (*psize > max_uint - 1)
352
0
                return_error(gs_error_VMerror);
353
0
            *p = (elt.value.boolval ? PtCr_true : PtCr_false);
354
0
            ++*psize;
355
0
            break;
356
14.9k
        case t_name:
357
14.9k
            if (!r_has_attr(&elt, a_executable))
358
24
                return_error(gs_error_rangecheck);
359
            /* Ensure we can't overflow max_uint, initially check the quick cases */
360
14.9k
            if (*psize > max_uint - 1)
361
0
                return_error(gs_error_VMerror);
362
14.9k
            name_string_ref(imemory, &elt, &elt);
363
14.9k
            if (!bytes_compare(elt.value.bytes, r_size(&elt),
364
14.9k
                               (const byte *)"true", 4)) {
365
0
                *p = PtCr_true;
366
0
                ++*psize;
367
0
                break;
368
0
            }
369
14.9k
            if (!bytes_compare(elt.value.bytes, r_size(&elt),
370
14.9k
                                      (const byte *)"false", 5)) {
371
0
                *p = PtCr_false;
372
0
                ++*psize;
373
0
                break;
374
0
            }
375
            /* Check if the name is a valid operator in systemdict */
376
14.9k
            if (dict_find(systemdict, &elt, &delp) <= 0)
377
53
                return_error(gs_error_undefined);
378
14.9k
            if (r_btype(delp) != t_operator)
379
213
                return_error(gs_error_typecheck);
380
14.7k
            if (!r_has_attr(delp, a_executable))
381
0
                return_error(gs_error_rangecheck);
382
14.7k
            elt = *delp;
383
            /* Fall into the operator case */
384
14.7k
        case t_operator: {
385
14.7k
            int j;
386
387
            /* Ensure we can't overflow max_uint, all operators are a single byte */
388
14.7k
            if (*psize > max_uint - 1)
389
0
                return_error(gs_error_VMerror);
390
529k
            for (j = 0; j < countof(calc_ops); ++j)
391
529k
                if (elt.value.opproc == calc_ops[j].proc) {
392
14.6k
                    *p = calc_ops[j].opcode;
393
14.6k
                    ++*psize;
394
14.6k
                    goto next;
395
14.6k
                }
396
14.7k
            return_error(gs_error_rangecheck);
397
14.7k
        }
398
0
        default: {
399
0
            if (!r_is_proc(&elt))
400
0
                return_error(gs_error_typecheck);
401
0
            if (depth == MAX_PSC_FUNCTION_NESTING)
402
0
                return_error(gs_error_limitcheck);
403
0
            if ((code = array_get(imemory, pref, ++i, &elt2)) < 0)
404
0
                return code;
405
            /* Ensure we can't overflow max_uint */
406
0
            if (*psize > max_uint - 3)
407
0
                return_error(gs_error_VMerror);
408
0
            *psize += 3;
409
0
            code = check_psc_function(i_ctx_p, &elt, depth + 1, ops, psize, AllowRepeat);
410
0
            if (code < 0)
411
0
                return code;
412
            /* Check for { proc } repeat | {proc} if | {proc1} {proc2} ifelse */
413
0
            if (resolves_to_oper(i_ctx_p, &elt2, zrepeat)) {
414
0
                if (!AllowRepeat)
415
0
                    return_error(gs_error_rangecheck);
416
                /* We need a byte to add the repeat end below */
417
0
                if (*psize > max_uint - 1)
418
0
                    return_error(gs_error_VMerror);
419
0
                if (ops) {
420
0
                    *p = PtCr_repeat;
421
0
                    if ((code = psc_fixup(p, ops + *psize)) < 0)
422
0
                        return code;
423
0
                    p = ops + *psize;
424
0
                    *p++ = PtCr_repeat_end;
425
0
                }
426
0
                *psize += 1;  /* extra room for repeat_end */
427
0
            } else if (resolves_to_oper(i_ctx_p, &elt2, zif)) {
428
0
                if (ops) {
429
0
                    *p = PtCr_if;
430
0
                    if ((code = psc_fixup(p, ops + *psize)) < 0)
431
0
                        return code;
432
0
                }
433
0
            } else if (!r_is_proc(&elt2))
434
0
                return_error(gs_error_rangecheck);
435
0
            else if ((code = array_get(imemory, pref, ++i, &elt3)) < 0)
436
0
                return code;
437
0
            else if (resolves_to_oper(i_ctx_p, &elt3, zifelse)) {
438
0
                if (ops) {
439
0
                    *p = PtCr_if;
440
0
                    if ((code = psc_fixup(p, ops + *psize + 3)) < 0)
441
0
                        return code;
442
0
                    p = ops + *psize;
443
0
                    *p = PtCr_else;
444
0
                }
445
                /* Ensure we can't overflow max_uint */
446
0
                if (*psize > max_uint - 3)
447
0
                    return_error(gs_error_VMerror);
448
0
                *psize += 3;
449
0
                code = check_psc_function(i_ctx_p, &elt2, depth + 1, ops, psize, AllowRepeat);
450
0
                if (code < 0)
451
0
                    return code;
452
0
                if (ops)
453
0
                    if ((code = psc_fixup(p, ops + *psize)) < 0)
454
0
                        return code;
455
0
            } else
456
0
                return_error(gs_error_rangecheck);
457
0
            }   /* end 'default' */
458
80.2k
        }
459
79.9k
    next:
460
79.9k
        DO_NOTHING;
461
79.9k
    }
462
13.3k
    return 0;
463
13.6k
}
464
#undef MAX_PSC_FUNCTION_NESTING
465
466
/* Check prototype */
467
build_function_proc(gs_build_function_4);
468
469
/* Finish building a FunctionType 4 (PostScript Calculator) function. */
470
int
471
gs_build_function_4(i_ctx_t *i_ctx_p, const ref *op, const gs_function_params_t * mnDR,
472
                    int depth, gs_function_t ** ppfn, gs_memory_t *mem)
473
0
{
474
0
    gs_function_PtCr_params_t params;
475
0
    ref *proc;
476
0
    int code;
477
0
    byte *ops;
478
0
    uint size;
479
0
    bool AllowRepeat = true; /* Default to permitting Repeat, devices which can't handle it implement the spec_op */
480
481
0
    *(gs_function_params_t *)&params = *mnDR;
482
0
    params.ops.data = 0;  /* in case of failure */
483
0
    params.ops.size = 0;  /* ditto */
484
0
    if (dict_find_string(op, "Function", &proc) <= 0) {
485
0
        code = gs_note_error(gs_error_rangecheck);
486
0
        goto fail;
487
0
    }
488
0
    if (!r_is_proc(proc)) {
489
0
        code = gs_note_error(gs_error_typecheck);
490
0
        goto fail;
491
0
    }
492
0
    size = 0;
493
494
    /* Check if the device allows the use of repeat in functions */
495
    /* We can't handle 'repeat' with pdfwrite since it emits FunctionType 4 */
496
0
    {
497
0
        char data[] = {"AllowPSRepeatFunctions"};
498
0
        dev_param_req_t request;
499
0
        gs_c_param_list list;
500
501
0
        gs_c_param_list_write(&list, i_ctx_p->pgs->device->memory);
502
        /* Stuff the data into a structure for passing to the spec_op */
503
0
        request.Param = data;
504
0
        request.list = &list;
505
0
        code = dev_proc(i_ctx_p->pgs->device, dev_spec_op)(i_ctx_p->pgs->device, gxdso_get_dev_param, &request, sizeof(dev_param_req_t));
506
0
        if (code < 0 && code != gs_error_undefined) {
507
0
            gs_c_param_list_release(&list);
508
0
            return code;
509
0
        }
510
0
        gs_c_param_list_read(&list);
511
0
        code = param_read_bool((gs_param_list *)&list,
512
0
            "AllowPSRepeatFunctions",
513
0
            &AllowRepeat);
514
0
        gs_c_param_list_release(&list);
515
0
        if (code < 0)
516
0
            return code;
517
0
    }
518
519
0
    code = check_psc_function(i_ctx_p, proc, 0, NULL, &size, AllowRepeat);
520
0
    if (code < 0)
521
0
        goto fail;
522
523
    /* We need an extra byte for the function return (see below)
524
     * strings are limited to max_uint size so make sure we won't overflow.
525
     */
526
0
    if (size == max_uint) {
527
0
        code = gs_note_error(gs_error_VMerror);
528
0
        goto fail;
529
0
    }
530
531
0
    ops = gs_alloc_string(mem, size + 1, "gs_build_function_4(ops)");
532
0
    if (ops == 0) {
533
0
        code = gs_note_error(gs_error_VMerror);
534
0
        goto fail;
535
0
    }
536
0
    size = 0;
537
0
    check_psc_function(i_ctx_p, proc, 0, ops, &size, AllowRepeat); /* can't fail */
538
0
    ops[size] = PtCr_return;
539
0
    params.ops.data = ops;
540
0
    params.ops.size = size + 1;
541
0
    code = gs_function_PtCr_init(ppfn, &params, mem);
542
0
    if (code >= 0)
543
0
        return 0;
544
    /* free_params will free the ops string */
545
0
fail:
546
0
    gs_function_PtCr_free_params(&params, mem);
547
0
    return code;
548
0
}
549
550
int make_type4_function(i_ctx_t * i_ctx_p, ref *arr, ref *pproc, gs_function_t **func)
551
6.98k
{
552
6.98k
    int code, num_components, CIESubst;
553
6.98k
    uint size;
554
6.98k
    byte *ops = NULL;
555
6.98k
    gs_function_PtCr_params_t params;
556
6.98k
    float *ptr;
557
6.98k
    ref alternatespace, *palternatespace = &alternatespace;
558
6.98k
    PS_colour_space_t *space, *altspace;
559
6.98k
    bool AllowRepeat = true; /* Default to permitting Repeat, devices which can't handle it implement the spec_op */
560
561
6.98k
    code = get_space_object(i_ctx_p, arr, &space);
562
6.98k
    if (code < 0)
563
0
        return code;
564
6.98k
    if (!space->alternateproc)
565
0
        return gs_error_typecheck;
566
6.98k
    code = space->alternateproc(i_ctx_p, arr, &palternatespace, &CIESubst);
567
6.98k
    if (code < 0)
568
0
        return code;
569
6.98k
    code = get_space_object(i_ctx_p, palternatespace, &altspace);
570
6.98k
    if (code < 0)
571
0
        return code;
572
573
6.98k
    code = space->numcomponents(i_ctx_p, arr, &num_components);
574
6.98k
    if (code < 0)
575
0
        return code;
576
6.98k
    ptr = (float *)gs_alloc_byte_array(imemory, num_components * 2, sizeof(float), "make_type4_function(Domain)");
577
6.98k
    if (!ptr)
578
0
        return gs_error_VMerror;
579
6.98k
    code = space->domain(i_ctx_p, arr, ptr);
580
6.98k
    if (code < 0) {
581
0
        gs_free_const_object(imemory, ptr, "make_type4_function(Domain)");
582
0
        return code;
583
0
    }
584
6.98k
    params.Domain = ptr;
585
6.98k
    params.m = num_components;
586
587
6.98k
    code = altspace->numcomponents(i_ctx_p, &alternatespace, &num_components);
588
6.98k
    if (code < 0) {
589
0
        gs_free_const_object(imemory, params.Domain, "make_type4_function(Domain)");
590
0
        return code;
591
0
    }
592
6.98k
    ptr = (float *)gs_alloc_byte_array(imemory, num_components * 2, sizeof(float), "make_type4_function(Range)");
593
6.98k
    if (!ptr) {
594
0
        gs_free_const_object(imemory, params.Domain, "make_type4_function(Domain)");
595
0
        return gs_error_VMerror;
596
0
    }
597
6.98k
    code = altspace->range(i_ctx_p, &alternatespace, ptr);
598
6.98k
    if (code < 0) {
599
0
        gs_free_const_object(imemory, ptr, "make_type4_function(Domain)");
600
0
        gs_free_const_object(imemory, params.Domain, "make_type4_function(Range)");
601
0
        return code;
602
0
    }
603
6.98k
    params.Range = ptr;
604
6.98k
    params.n = num_components;
605
606
6.98k
    params.ops.data = 0;  /* in case of failure, see gs_function_PtCr_free_params */
607
6.98k
    params.ops.size = 0;  /* ditto */
608
6.98k
    size = 0;
609
610
    /* Check if the device allows the use of repeat in functions */
611
    /* We can't handle 'repeat' with pdfwrite since it emits FunctionType 4 */
612
6.98k
    {
613
6.98k
        char data[] = {"AllowPSRepeatFunctions"};
614
6.98k
        dev_param_req_t request;
615
6.98k
        gs_c_param_list list;
616
617
6.98k
        gs_c_param_list_write(&list, i_ctx_p->pgs->device->memory);
618
        /* Stuff the data into a structure for passing to the spec_op */
619
6.98k
        request.Param = data;
620
6.98k
        request.list = &list;
621
6.98k
        code = dev_proc(i_ctx_p->pgs->device, dev_spec_op)(i_ctx_p->pgs->device, gxdso_get_dev_param, &request, sizeof(dev_param_req_t));
622
6.98k
        if (code < 0 && code != gs_error_undefined) {
623
0
            gs_c_param_list_release(&list);
624
0
            return code;
625
0
        }
626
6.98k
        gs_c_param_list_read(&list);
627
6.98k
        code = param_read_bool((gs_param_list *)&list,
628
6.98k
            "AllowPSRepeatFunctions",
629
6.98k
            &AllowRepeat);
630
6.98k
        gs_c_param_list_release(&list);
631
6.98k
        if (code < 0)
632
0
            return code;
633
6.98k
    }
634
635
6.98k
    code = check_psc_function(i_ctx_p, (const ref *)pproc, 0, NULL, &size, AllowRepeat);
636
6.98k
    if (code < 0)
637
307
        goto error;
638
639
    /* We need an extra byte for the function return (see below)
640
     * strings are limited to max_uint size so make sure we won't overflow.
641
     */
642
6.67k
    if (size == max_uint) {
643
0
        code = gs_note_error(gs_error_VMerror);
644
0
        goto error;
645
0
    }
646
647
6.67k
    ops = gs_alloc_string(imemory, size + 1, "make_type4_function(ops)");
648
6.67k
    if (ops == NULL) {
649
0
        code = gs_note_error(gs_error_VMerror);
650
0
        goto error;
651
0
    }
652
6.67k
    size = 0;
653
6.67k
    check_psc_function(i_ctx_p, (const ref *)pproc, 0, ops, &size, AllowRepeat); /* can't fail */
654
6.67k
    ops[size] = PtCr_return;
655
6.67k
    params.ops.data = ops;
656
6.67k
    params.ops.size = size + 1;
657
6.67k
    code = gs_function_PtCr_init(func, &params, imemory);
658
6.67k
    if (code < 0)
659
0
        goto error;
660
661
6.67k
    return code;
662
663
307
error:
664
    /* free_params will free the ops string */
665
307
    gs_function_PtCr_free_params(&params, imemory);
666
307
    return code;
667
6.67k
}