/* Finish building a FunctionType 0 (Sampled) function. */ int gs_build_function_0(i_ctx_t *i_ctx_p, const ref *op, const gs_function_params_t * mnDR, int depth, gs_function_t ** ppfn, gs_memory_t *mem) { gs_function_Sd_params_t params; ref *pDataSource; int code; *(gs_function_params_t *) & params = *mnDR; params.Encode = 0; params.Decode = 0; params.Size = 0; if ((code = dict_find_string(op, "DataSource", &pDataSource)) <= 0) return (code < 0 ? code : gs_note_error(e_rangecheck)); switch (r_type(pDataSource)) { case t_string: data_source_init_string2(¶ms.DataSource, pDataSource->value.const_bytes, r_size(pDataSource)); break; case t_file: { stream *s; check_read_known_file_else(s, pDataSource, return_error, return_error(e_invalidfileaccess)); if (!(s->modes & s_mode_seek)) return_error(e_ioerror); data_source_init_stream(¶ms.DataSource, s); break; } default: return_error(e_rangecheck); } if ((code = dict_int_param(op, "Order", 1, 3, 1, ¶ms.Order)) < 0 || (code = dict_int_param(op, "BitsPerSample", 1, 32, 0, ¶ms.BitsPerSample)) < 0 || ((code = fn_build_float_array(op, "Encode", false, true, ¶ms.Encode, mem)) != 2 * params.m && (code != 0 || params.Encode != 0)) || ((code = fn_build_float_array(op, "Decode", false, true, ¶ms.Decode, mem)) != 2 * params.n && (code != 0 || params.Decode != 0)) ) { goto fail; } { int *ptr = (int *) gs_alloc_byte_array(mem, params.m, sizeof(int), "Size"); if (ptr == 0) { code = gs_note_error(e_VMerror); goto fail; } params.Size = ptr; code = dict_ints_param(op, "Size", params.m, ptr); if (code != params.m) goto fail; } code = gs_function_Sd_init(ppfn, ¶ms, mem); if (code >= 0) return 0; fail: gs_function_Sd_free_params(¶ms, mem); return (code < 0 ? code : gs_note_error(e_rangecheck)); }
/* Finish building a FunctionType 3 (1-Input Stitching) function. */ int gs_build_function_3(i_ctx_t *i_ctx_p, const ref *op, const gs_function_params_t * mnDR, int depth, gs_function_t ** ppfn, gs_memory_t *mem) { gs_function_1ItSg_params_t params; int code; *(gs_function_params_t *) & params = *mnDR; params.Functions = 0; params.Bounds = 0; params.Encode = 0; { ref *pFunctions; gs_function_t **ptr; int i; if ((code = dict_find_string(op, "Functions", &pFunctions)) <= 0) return (code < 0 ? code : gs_note_error(e_rangecheck)); check_array_only(*pFunctions); params.k = r_size(pFunctions); code = alloc_function_array(params.k, &ptr, mem); if (code < 0) return code; params.Functions = (const gs_function_t * const *)ptr; for (i = 0; i < params.k; ++i) { ref subfn; array_get(mem, pFunctions, (long)i, &subfn); code = fn_build_sub_function(i_ctx_p, &subfn, &ptr[i], depth, mem); if (code < 0) goto fail; } } if ((code = fn_build_float_array(op, "Bounds", true, false, ¶ms.Bounds, mem)) != params.k - 1 || (code = fn_build_float_array(op, "Encode", true, true, ¶ms.Encode, mem)) != 2 * params.k ) goto fail; if (params.Range == 0) params.n = params.Functions[0]->params.n; code = gs_function_1ItSg_init(ppfn, ¶ms, mem); if (code >= 0) return 0; fail: gs_function_1ItSg_free_params(¶ms, mem); return (code < 0 ? code : gs_note_error(e_rangecheck)); }
/* Finish building a FunctionType 3 (1-Input Stitching) function. */ int gs_build_function_3(i_ctx_t *i_ctx_p, const ref *op, const gs_function_params_t * mnDR, int depth, gs_function_t ** ppfn, gs_memory_t *mem) { gs_function_1ItSg_params_t params; int code; extern bool CPSI_mode; *(gs_function_params_t *) & params = *mnDR; params.Functions = 0; params.Bounds = 0; params.Encode = 0; { ref *pFunctions; gs_function_t **ptr; int i; if ((code = dict_find_string(op, "Functions", &pFunctions)) <= 0) return (code < 0 ? code : gs_note_error(e_rangecheck)); check_array_only(*pFunctions); params.k = r_size(pFunctions); code = alloc_function_array(params.k, &ptr, mem); if (code < 0) return code; params.Functions = (const gs_function_t * const *)ptr; for (i = 0; i < params.k; ++i) { ref subfn; array_get(mem, pFunctions, (long)i, &subfn); code = fn_build_sub_function(i_ctx_p, &subfn, &ptr[i], depth, mem, 0, 0); if (code < 0) goto fail; } } if ((code = fn_build_float_array(op, "Bounds", true, false, ¶ms.Bounds, mem)) != params.k - 1) goto fail; if (CPSI_mode) { /* Adobe implementation doesn't check the Encode length. */ /* Extra elements are ignored; missing elements are filled with 0. */ /* CET 12-14m.ps depends on this bug */ uint sz, k2 = 2 * params.k; ref *encode; float *p = (float *)gs_alloc_byte_array(mem, k2, sizeof(float), "Encode"); params.Encode = p; if (p == 0) { code = gs_note_error(e_VMerror); goto fail; } if (dict_find_string(op, "Encode", &encode) <= 0) { code = gs_note_error(e_undefined); goto fail; } if (!r_is_array(encode)) { code = gs_note_error(e_typecheck); goto fail; } sz = min(k2, r_size(encode)); code = process_float_array(mem, encode, sz, p); if (code < 0) goto fail; while (sz < k2) p[sz++] = 0.0; } else if ((code = fn_build_float_array(op, "Encode", true, true, ¶ms.Encode, mem)) != 2 * params.k) goto fail; if (params.Range == 0) params.n = params.Functions[0]->params.n; code = gs_function_1ItSg_init(ppfn, ¶ms, mem); if (code >= 0) return 0; fail: gs_function_1ItSg_free_params(¶ms, mem); return (code < 0 ? code : gs_note_error(e_rangecheck)); }
int fn_build_sub_function(i_ctx_t *i_ctx_p, const ref * op, gs_function_t ** ppfn, int depth, gs_memory_t *mem, const float *shading_domain, const int num_inputs) { int j, code, type; uint i; gs_function_params_t params; if (depth > MAX_SUB_FUNCTION_DEPTH) return_error(gs_error_limitcheck); check_type(*op, t_dictionary); code = dict_int_param(op, "FunctionType", 0, max_int, -1, &type); if (code < 0) return code; for (i = 0; i < build_function_type_table_count; ++i) if (build_function_type_table[i].type == type) break; if (i == build_function_type_table_count) return_error(gs_error_rangecheck); /* Collect parameters common to all function types. */ params.Domain = 0; params.Range = 0; code = fn_build_float_array(op, "Domain", true, true, ¶ms.Domain, mem); if (code < 0) { gs_errorinfo_put_pair_from_dict(i_ctx_p, op, "Domain"); goto fail; } params.m = code >> 1; for (j = 0; j < params.m << 1; j += 2) { if (params.Domain[j] >= params.Domain[j + 1]) { code = gs_note_error(gs_error_rangecheck); gs_errorinfo_put_pair_from_dict(i_ctx_p, op, "Domain"); goto fail; } } if (shading_domain) { /* Each function dictionary's domain must be a superset of that of * the shading dictionary. PLRM3 p.265. CET 12-14c. We do this check * here because Adobe checks Domain before checking other parameters. */ if (num_inputs != params.m) code = gs_note_error(gs_error_rangecheck); for (j = 0; j < 2*num_inputs && code >= 0; j += 2) { if (params.Domain[j] > shading_domain[j] || params.Domain[j+1] < shading_domain[j+1] ) { code = gs_note_error(gs_error_rangecheck); } } if (code < 0) { gs_errorinfo_put_pair_from_dict(i_ctx_p, op, "Domain"); goto fail; } } code = fn_build_float_array(op, "Range", false, true, ¶ms.Range, mem); if (code < 0) goto fail; params.n = code >> 1; /* Finish building the function. */ /* If this fails, it will free all the parameters. */ return (*build_function_type_table[i].proc) (i_ctx_p, op, ¶ms, depth + 1, ppfn, mem); fail: gs_free_const_object(mem, params.Range, "Range"); gs_free_const_object(mem, params.Domain, "Domain"); return code; }
/* * Fill in the data for a function type 0 parameter object to be used while * we collect the data for the data cube. At the end of the process, we * will create a function type 0 object to be used to calculate values * as a replacement for the original function. */ static int cube_build_func0(const ref * pdict, gs_function_Sd_params_t * params, gs_memory_t *mem) { byte * bytes = 0; int code, i; int total_size; if ((code = dict_int_param(pdict, "Order", 1, 3, 1, ¶ms->Order)) < 0 || (code = dict_int_param(pdict, "BitsPerSample", 1, 32, 0, ¶ms->BitsPerSample)) < 0 || ((code = params->m = fn_build_float_array(pdict, "Domain", false, true, ¶ms->Domain, mem)) < 0 ) || ((code = params->n = fn_build_float_array(pdict, "Range", false, true, ¶ms->Range, mem)) < 0) ) { goto fail; } /* * The previous logic set the size of m and n to the size of the Domain * and Range arrays. This is twice the actual size. Correct this and * check for valid values. */ params->m >>= 1; params->n >>= 1; if (params->m == 0 || params->n == 0 || params->m > MAX_NUM_INPUTS || params->n > MAX_NUM_OUTPUTS) { code = gs_note_error(e_rangecheck); goto fail; } /* * The Size array may or not be specified. If it is not specified then * we need to determine a set of default values for the Size array. */ { int *ptr = (int *) gs_alloc_byte_array(mem, params->m, sizeof(int), "Size"); if (ptr == NULL) { code = gs_note_error(e_VMerror); goto fail; } params->Size = ptr; code = dict_ints_param(mem, pdict, "Size", params->m, ptr); if (code < 0) goto fail; if (code == 0) { /* * The Size array has not been specified. Determine a default * set of values. */ code = determine_sampled_data_size(params->m, params->n, params->BitsPerSample, (int *)params->Size); if (code < 0) goto fail; } else { /* Size array specified - verify valid */ if (code != params->m || !valid_cube_size(params->m, params->n, params->BitsPerSample, params->Size)) code = gs_note_error(e_rangecheck); goto fail; } } /* * Determine space required for the sample data storage. */ total_size = params->n * bits2bytes(params->BitsPerSample); for (i = 0; i < params->m; i++) total_size *= params->Size[i]; /* * Allocate space for the data cube itself. */ bytes = gs_alloc_byte_array(mem, total_size, 1, "cube_build_func0(bytes)"); if (!bytes) { code = gs_note_error(e_VMerror); goto fail; } data_source_init_bytes(¶ms->DataSource, (const unsigned char *)bytes, total_size); return 0; fail: gs_function_Sd_free_params(params, mem); return (code < 0 ? code : gs_note_error(e_rangecheck)); }