static int zpathforall(i_ctx_t *i_ctx_p) { os_ptr op = osp; gs_path_enum *penum; int code; check_proc(op[-3]); check_proc(op[-2]); check_proc(op[-1]); check_proc(*op); check_estack(8); if ((penum = gs_path_enum_alloc(imemory, "pathforall")) == 0) return_error(e_VMerror); code = gs_path_enum_init(penum, igs); if (code < 0) { ifree_object(penum, "path_cleanup"); return code; } /* Push a mark, the four procedures, and the path enumerator. */ push_mark_estack(es_for, path_cleanup); /* iterator */ memcpy(esp + 1, op - 3, 4 * sizeof(ref)); /* 4 procs */ esp += 5; make_istruct(esp, 0, penum); push_op_estack(path_continue); pop(4); op -= 4; return o_push_estack; }
/* <pattern> <matrix> <shading> .buildshadingpattern <pattern> <instance> */ static int zbuildshadingpattern(i_ctx_t *i_ctx_p) { os_ptr op = osp; os_ptr op2 = op - 2; gs_matrix mat; gs_pattern2_template_t templat; int_pattern *pdata; gs_client_color cc_instance; int code; check_type(*op2, t_dictionary); check_dict_read(*op2); gs_pattern2_init(&templat); if ((code = read_matrix(imemory, op - 1, &mat)) < 0 || (code = dict_uid_param(op2, &templat.uid, 1, imemory, i_ctx_p)) != 1 || (code = shading_param(op, &templat.Shading)) < 0 || (code = int_pattern_alloc(&pdata, op2, imemory)) < 0 ) return_error((code < 0 ? code : gs_error_rangecheck)); templat.client_data = pdata; code = gs_make_pattern(&cc_instance, (const gs_pattern_template_t *)&templat, &mat, igs, imemory); if (code < 0) { ifree_object(pdata, "int_pattern"); return code; } make_istruct(op - 1, a_readonly, cc_instance.pattern); pop(1); return code; }
static int zfilenameforall(i_ctx_t *i_ctx_p) { os_ptr op = osp; file_enum *pfen; gx_io_device *iodev = NULL; gs_parsed_file_name_t pname; int code = 0; check_write_type(*op, t_string); check_proc(op[-1]); check_read_type(op[-2], t_string); /* Push a mark, the iodev, devicenamelen, the scratch string, the enumerator, */ /* and the procedure, and invoke the continuation. */ check_estack(7); /* Get the iodevice */ code = parse_file_name(op - 2, &pname, i_ctx_p->LockFilePermissions); if (code < 0) return code; iodev = (pname.iodev == NULL) ? iodev_default : pname.iodev; /* Check for several conditions that just cause us to return success */ if (pname.len == 0 || iodev->procs.enumerate_files == iodev_no_enumerate_files) { pop(3); return 0; /* no pattern, or device not found -- just return */ } pfen = iodev->procs.enumerate_files(iodev, (const char *)pname.fname, pname.len, imemory); if (pfen == 0) return_error(e_VMerror); push_mark_estack(es_for, file_cleanup); ++esp; make_istruct(esp, 0, iodev); ++esp; make_int(esp, r_size(op-2) - pname.len); *++esp = *op; ++esp; make_istruct(esp, 0, pfen); *++esp = op[-1]; pop(3); code = file_continue(i_ctx_p); return (code == o_pop_estack ? o_push_estack : code); }
/* * Set up to collect the data for the sampled function. This is used for * those alternate tint transforms that cannot be converted into a * type 4 function. */ static int sampled_data_setup(i_ctx_t *i_ctx_p, gs_function_t *pfn, const ref * pproc, int (*finish_proc)(i_ctx_t *), gs_memory_t * mem) { os_ptr op = osp; gs_sampled_data_enum *penum; int i; gs_function_Sd_params_t * params = (gs_function_Sd_params_t *)&pfn->params; check_estack(estack_storage + 1); /* Verify space on estack */ check_ostack(params->m + O_STACK_PAD); /* and the operand stack */ check_ostack(params->n + O_STACK_PAD); /* * Allocate space for the enumerator data structure. */ penum = gs_sampled_data_enum_alloc(imemory, "zbuildsampledfuntion(params)"); if (penum == NULL) return_error(e_VMerror); /* Initialize data in the enumeration structure */ penum->pfn = pfn; for(i=0; i< params->m; i++) penum->indexes[i] = 0; /* * Save stack depth for checking the correct number of values on stack * after the function, which is being sampled, is called. */ penum->o_stack_depth = ref_stack_count(&o_stack); /* * Note: As previously mentioned, we are putting some spare (unused) stack * space under the input values in case the function unbalances the stack. * It is possible for the function to pop or change values on the stack * outside of the input values. (This has been found to happen with some * proc sets from Adobe.) */ push(O_STACK_PAD); for (i = 0; i < O_STACK_PAD; i++) /* Set space = null */ make_null(op - i); /* Push everything on the estack */ esp += estack_storage; make_op_estack(esp - 2, finish_proc); /* Finish proc onto estack */ sample_proc = *pproc; /* Save function to be sampled */ make_istruct(esp, 0, penum); /* Color cube enumeration structure */ push_op_estack(sampled_data_sample); /* Start sampling data */ return o_push_estack; }
/* * Do a callout to an OtherSubr implemented in PostScript. * The caller must have done a check_estack(4 + num_args). */ static int type1_call_OtherSubr(i_ctx_t *i_ctx_p, const gs_type1exec_state * pcxs, int (*cont) (i_ctx_t *), const ref * pos) { /* Move the Type 1 interpreter state to the heap. */ gs_type1exec_state *hpcxs = ialloc_struct(gs_type1exec_state, &st_gs_type1exec_state, "type1_call_OtherSubr"); if (hpcxs == 0) return_error(e_VMerror); *hpcxs = *pcxs; gs_type1_set_callback_data(&hpcxs->cis, hpcxs); push_mark_estack(es_show, op_type1_cleanup); ++esp; make_istruct(esp, 0, hpcxs); return type1_push_OtherSubr(i_ctx_p, pcxs, cont, pos); }
/* - gstate <gstate> */ int zgstate(i_ctx_t *i_ctx_p) { os_ptr op = osp; int code = gstate_check_space(i_ctx_p, istate, icurrent_space); igstate_obj *pigo; gs_state *pnew; int_gstate *isp; if (code < 0) return code; pigo = ialloc_struct(igstate_obj, &st_igstate_obj, "gstate"); if (pigo == 0) return_error(e_VMerror); pnew = gs_state_copy(igs, imemory); if (pnew == 0) { ifree_object(pigo, "gstate"); return_error(e_VMerror); } isp = gs_int_gstate(pnew); int_gstate_map_refs(isp, ref_mark_new); push(1); /* * Since igstate_obj isn't a ref, but only contains a ref, save won't * clear its l_new bit automatically, and restore won't set it * automatically; we have to make sure this ref is on the changes chain. */ make_iastruct(op, a_all, pigo); #if 0 /* Bug 689849 "gstate leaks memory" */ make_null(&pigo->gstate); ref_save(op, &pigo->gstate, "gstate"); make_istruct_new(&pigo->gstate, 0, pnew); #else make_istruct(&pigo->gstate, 0, pnew); #endif return 0; }
static int zsethalftone5(i_ctx_t *i_ctx_p) { os_ptr op = osp; uint count; gs_halftone_component *phtc; gs_halftone_component *pc; int code = 0; int j; gs_halftone *pht; gx_device_halftone *pdht; ref sprocs[GS_CLIENT_COLOR_MAX_COMPONENTS + 1]; ref tprocs[GS_CLIENT_COLOR_MAX_COMPONENTS + 1]; gs_memory_t *mem; uint edepth = ref_stack_count(&e_stack); int npop = 2; int dict_enum = dict_first(op); ref rvalue[2]; int cname, colorant_number; byte * pname; uint name_size; int halftonetype, type = 0; gs_state *pgs = igs; int space_index = r_space_index(op - 1); mem = (gs_memory_t *) idmemory->spaces_indexed[space_index]; check_type(*op, t_dictionary); check_dict_read(*op); check_type(op[-1], t_dictionary); check_dict_read(op[-1]); /* * We think that Type 2 and Type 4 halftones, like * screens set by setcolorscreen, adapt automatically to * the device color space, so we need to mark them * with a different internal halftone type. */ dict_int_param(op - 1, "HalftoneType", 1, 5, 0, &type); halftonetype = (type == 2 || type == 4) ? ht_type_multiple_colorscreen : ht_type_multiple; /* Count how many components that we will actually use. */ for (count = 0; ;) { bool have_default = false; /* Move to next element in the dictionary */ if ((dict_enum = dict_next(op, dict_enum, rvalue)) == -1) break; /* * Verify that we have a valid component. We may have a * /HalfToneType entry. */ if (!r_has_type(&rvalue[1], t_dictionary)) continue; /* Get the name of the component verify that we will use it. */ cname = name_index(mem, &rvalue[0]); code = gs_get_colorname_string(mem, cname, &pname, &name_size); if (code < 0) break; colorant_number = gs_cname_to_colorant_number(pgs, pname, name_size, halftonetype); if (colorant_number < 0) continue; else if (colorant_number == GX_DEVICE_COLOR_MAX_COMPONENTS) { /* If here then we have the "Default" component */ if (have_default) return_error(e_rangecheck); have_default = true; } count++; /* * Check to see if we have already reached the legal number of * components. */ if (count > GS_CLIENT_COLOR_MAX_COMPONENTS + 1) { code = gs_note_error(e_rangecheck); break; } } check_estack(5); /* for sampling Type 1 screens */ refset_null(sprocs, count); refset_null(tprocs, count); rc_alloc_struct_0(pht, gs_halftone, &st_halftone, imemory, pht = 0, ".sethalftone5"); phtc = gs_alloc_struct_array(mem, count, gs_halftone_component, &st_ht_component_element, ".sethalftone5"); rc_alloc_struct_0(pdht, gx_device_halftone, &st_device_halftone, imemory, pdht = 0, ".sethalftone5"); if (pht == 0 || phtc == 0 || pdht == 0) { j = 0; /* Quiet the compiler: gs_note_error isn't necessarily identity, so j could be left ununitialized. */ code = gs_note_error(e_VMerror); } else { dict_enum = dict_first(op); for (j = 0, pc = phtc; ;) { int type; /* Move to next element in the dictionary */ if ((dict_enum = dict_next(op, dict_enum, rvalue)) == -1) break; /* * Verify that we have a valid component. We may have a * /HalfToneType entry. */ if (!r_has_type(&rvalue[1], t_dictionary)) continue; /* Get the name of the component */ cname = name_index(mem, &rvalue[0]); code = gs_get_colorname_string(mem, cname, &pname, &name_size); if (code < 0) break; colorant_number = gs_cname_to_colorant_number(pgs, pname, name_size, halftonetype); if (colorant_number < 0) continue; /* Do not use this component */ pc->cname = cname; pc->comp_number = colorant_number; /* Now process the component dictionary */ check_dict_read(rvalue[1]); if (dict_int_param(&rvalue[1], "HalftoneType", 1, 7, 0, &type) < 0) { code = gs_note_error(e_typecheck); break; } switch (type) { default: code = gs_note_error(e_rangecheck); break; case 1: code = dict_spot_params(&rvalue[1], &pc->params.spot, sprocs + j, tprocs + j); pc->params.spot.screen.spot_function = spot1_dummy; pc->type = ht_type_spot; break; case 3: code = dict_threshold_params(&rvalue[1], &pc->params.threshold, tprocs + j); pc->type = ht_type_threshold; break; case 7: code = dict_threshold2_params(&rvalue[1], &pc->params.threshold2, tprocs + j, imemory); pc->type = ht_type_threshold2; break; } if (code < 0) break; pc++; j++; } } if (code >= 0) { pht->type = halftonetype; pht->params.multiple.components = phtc; pht->params.multiple.num_comp = j; pht->params.multiple.get_colorname_string = gs_get_colorname_string; code = gs_sethalftone_prepare(igs, pht, pdht); } if (code >= 0) { /* * Put the actual frequency and angle in the spot function component dictionaries. */ dict_enum = dict_first(op); for (pc = phtc; ; ) { /* Move to next element in the dictionary */ if ((dict_enum = dict_next(op, dict_enum, rvalue)) == -1) break; /* Verify that we have a valid component */ if (!r_has_type(&rvalue[1], t_dictionary)) continue; /* Get the name of the component and verify that we will use it. */ cname = name_index(mem, &rvalue[0]); code = gs_get_colorname_string(mem, cname, &pname, &name_size); if (code < 0) break; colorant_number = gs_cname_to_colorant_number(pgs, pname, name_size, halftonetype); if (colorant_number < 0) continue; if (pc->type == ht_type_spot) { code = dict_spot_results(i_ctx_p, &rvalue[1], &pc->params.spot); if (code < 0) break; } pc++; } } if (code >= 0) { /* * Schedule the sampling of any Type 1 screens, * and any (Type 1 or Type 3) TransferFunctions. * Save the stack depths in case we have to back out. */ uint odepth = ref_stack_count(&o_stack); ref odict, odict5; odict = op[-1]; odict5 = *op; pop(2); op = osp; esp += 5; make_mark_estack(esp - 4, es_other, sethalftone_cleanup); esp[-3] = odict; make_istruct(esp - 2, 0, pht); make_istruct(esp - 1, 0, pdht); make_op_estack(esp, sethalftone_finish); for (j = 0; j < count; j++) { gx_ht_order *porder = NULL; if (pdht->components == 0) porder = &pdht->order; else { /* Find the component in pdht that matches component j in the pht; gs_sethalftone_prepare() may permute these. */ int k; int comp_number = phtc[j].comp_number; for (k = 0; k < count; k++) { if (pdht->components[k].comp_number == comp_number) { porder = &pdht->components[k].corder; break; } } } switch (phtc[j].type) { case ht_type_spot: code = zscreen_enum_init(i_ctx_p, porder, &phtc[j].params.spot.screen, &sprocs[j], 0, 0, space_index); if (code < 0) break; /* falls through */ case ht_type_threshold: if (!r_has_type(tprocs + j, t__invalid)) { /* Schedule TransferFunction sampling. */ /****** check_xstack IS WRONG ******/ check_ostack(zcolor_remap_one_ostack); check_estack(zcolor_remap_one_estack); code = zcolor_remap_one(i_ctx_p, tprocs + j, porder->transfer, igs, zcolor_remap_one_finish); op = osp; } break; default: /* not possible here, but to keep */ /* the compilers happy.... */ ; } if (code < 0) { /* Restore the stack. */ ref_stack_pop_to(&o_stack, odepth); ref_stack_pop_to(&e_stack, edepth); op = osp; op[-1] = odict; *op = odict5; break; } npop = 0; } } if (code < 0) { gs_free_object(mem, pdht, ".sethalftone5"); gs_free_object(mem, phtc, ".sethalftone5"); gs_free_object(mem, pht, ".sethalftone5"); return code; } pop(npop); return (ref_stack_count(&e_stack) > edepth ? o_push_estack : 0); }
/* Finish setting up a text operator. */ int op_show_finish_setup(i_ctx_t *i_ctx_p, gs_text_enum_t * penum, int npop, op_proc_t endproc /* end procedure */ ) { gs_text_enum_t *osenum = op_show_find(i_ctx_p); es_ptr ep = esp + snumpush; gs_glyph glyph; if (gs_currentcpsimode(igs->memory)) { /* CET 14-03.PS page 2 emits rangecheck before rendering a character. Early check the text to font compatibility with decomposing the text into characters.*/ int code = gs_text_count_chars(igs, gs_get_text_params(penum), imemory); if (code < 0) return code; } /* * If we are in the procedure of a cshow for a CID font and this is * a show operator, do something special, per the Red Book. */ if (osenum && SHOW_IS_ALL_OF(osenum, TEXT_FROM_STRING | TEXT_DO_NONE | TEXT_INTERVENE) && SHOW_IS_ALL_OF(penum, TEXT_FROM_STRING | TEXT_RETURN_WIDTH) && (glyph = gs_text_current_glyph(osenum)) != gs_no_glyph && glyph >= gs_min_cid_glyph && /* According to PLRM, we don't need to raise a rangecheck error, if currentfont is changed in the proc of the operator 'cshow'. */ gs_default_same_font (gs_text_current_font(osenum), gs_text_current_font(penum), true) ) { gs_text_params_t text; if (!(penum->text.size == 1 && penum->text.data.bytes[0] == (gs_text_current_char(osenum) & 0xff)) ) return_error(e_rangecheck); text = penum->text; text.operation = (text.operation & ~(TEXT_FROM_STRING | TEXT_FROM_BYTES | TEXT_FROM_CHARS | TEXT_FROM_GLYPHS | TEXT_FROM_SINGLE_CHAR)) | TEXT_FROM_SINGLE_GLYPH; text.data.d_glyph = glyph; text.size = 1; gs_text_restart(penum, &text); } if (osenum && osenum->current_font->FontType == ft_user_defined && osenum->orig_font->FontType == ft_composite && ((const gs_font_type0 *)osenum->orig_font)->data.FMapType == fmap_CMap) { /* A special behavior defined in PLRM3 section 5.11 page 389. */ penum->outer_CID = osenum->returned.current_glyph; } if (osenum == NULL && !(penum->text.operation & (TEXT_FROM_GLYPHS | TEXT_FROM_SINGLE_GLYPH))) { int ft = igs->root_font->FontType; if ((ft >= ft_CID_encrypted && ft <= ft_CID_TrueType) || ft == ft_CID_bitmap) return_error(e_typecheck); } make_mark_estack(ep - (snumpush - 1), es_show, op_show_cleanup); if (endproc == NULL) endproc = finish_show; make_null(&esslot(ep)); make_int(&esodepth(ep), ref_stack_count_inline(&o_stack) - npop); /* Save stack depth for */ make_int(&esddepth(ep), ref_stack_count_inline(&d_stack)); /* correct interrupt processing */ make_int(&esgslevel(ep), igs->level); make_null(&essfont(ep)); make_null(&esrfont(ep)); make_op_estack(&eseproc(ep), endproc); make_istruct(ep, 0, penum); esp = ep; return 0; }
/* * Handle a scan_Comment or scan_DSC_Comment return from gs_scan_token * (scan_code) by calling out to %Process[DSC]Comment. The continuation * procedure expects the scanner state on the o-stack. */ int ztoken_handle_comment(i_ctx_t *i_ctx_p, scanner_state *sstate, const ref *ptoken, int scan_code, bool save, bool push_file, op_proc_t cont) { const char *proc_name; scanner_state *pstate; os_ptr op; ref *ppcproc; int code; switch (scan_code) { case scan_Comment: proc_name = "%ProcessComment"; break; case scan_DSC_Comment: proc_name = "%ProcessDSCComment"; break; default: return_error(e_Fatal); /* can't happen */ } /* * We can't use check_ostack here, because it returns on overflow. */ /*check_ostack(2);*/ if (ostop - osp < 2) { code = ref_stack_extend(&o_stack, 2); if (code < 0) return code; } check_estack(3); code = name_enter_string(imemory, proc_name, esp + 3); if (code < 0) return code; if (save) { pstate = (scanner_state *)ialloc_struct(scanner_state_dynamic, &st_scanner_state_dynamic, "ztoken_handle_comment"); if (pstate == 0) return_error(e_VMerror); ((scanner_state_dynamic *)pstate)->mem = imemory; *pstate = *sstate; } else pstate = sstate; /* Save the token now -- it might be on the e-stack. */ if (!pstate->s_pstack) osp[2] = *ptoken; /* * Push the continuation, scanner state, file, and callout procedure * on the e-stack. */ make_op_estack(esp + 1, cont); make_istruct(esp + 2, 0, pstate); ppcproc = dict_find_name(esp + 3); if (ppcproc == 0) { /* * This can only happen during initialization. * Pop the comment string from the o-stack if needed (see below). */ if (pstate->s_pstack) --osp; esp += 2; /* do run the continuation */ } else { /* * Push the file and comment string on the o-stack. * If we were inside { }, the comment string is already on the stack. */ if (pstate->s_pstack) { op = ++osp; *op = op[-1]; } else { op = osp += 2; /* *op = *ptoken; */ /* saved above */ } op[-1] = pstate->s_file; esp[3] = *ppcproc; esp += 3; } return o_push_estack; }
static int zsetcolorscreen(i_ctx_t *i_ctx_p) { os_ptr op = osp; gs_colorscreen_halftone cscreen; ref sprocs[4]; gs_halftone *pht; gx_device_halftone *pdht; int i; int code = 0; int space = 0; gs_memory_t *mem; for (i = 0; i < 4; i++) { os_ptr op1 = op - 9 + i * 3; int code = zscreen_params(op1, &cscreen.screens.indexed[i]); if (code < 0) return code; cscreen.screens.indexed[i].spot_function = spot_dummy; sprocs[i] = *op1; space = max(space, r_space_index(op1)); } mem = (gs_memory_t *)idmemory->spaces_indexed[space]; check_estack(8); /* for sampling screens */ rc_alloc_struct_0(pht, gs_halftone, &st_halftone, mem, pht = 0, "setcolorscreen(halftone)"); rc_alloc_struct_0(pdht, gx_device_halftone, &st_device_halftone, mem, pdht = 0, "setcolorscreen(device halftone)"); if (pht == 0 || pdht == 0) code = gs_note_error(e_VMerror); else { pht->type = ht_type_colorscreen; pht->params.colorscreen = cscreen; code = gs_sethalftone_prepare(igs, pht, pdht); } if (code >= 0) { /* Schedule the sampling of the screens. */ es_ptr esp0 = esp; /* for backing out */ esp += 8; make_mark_estack(esp - 7, es_other, setcolorscreen_cleanup); memcpy(esp - 6, sprocs, sizeof(ref) * 4); /* procs */ make_istruct(esp - 2, 0, pht); make_istruct(esp - 1, 0, pdht); make_op_estack(esp, setcolorscreen_finish); for (i = 0; i < 4; i++) { /* Shuffle the indices to correspond to */ /* the component order. */ code = zscreen_enum_init(i_ctx_p, &pdht->components[(i + 1) & 3].corder, &pht->params.colorscreen.screens.indexed[i], &sprocs[i], 0, 0, space); if (code < 0) { esp = esp0; break; } } } if (code < 0) { gs_free_object(mem, pdht, "setcolorscreen(device halftone)"); gs_free_object(mem, pht, "setcolorscreen(halftone)"); return code; } pop(12); return o_push_estack; }