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); }
/* This opens %statementedit% or %lineedit% and is also the * continuation proc for callouts. * Input: * string is the statement/line buffer, * int is the write index into string * bool is true if %statementedit% * file is stdin * Output: * file is a string based stream * We store the line being read in a PostScript string. * This limits the size to max_string_size (64k). * This could be increased by storing the input line in something * other than a PostScript string. */ int zfilelineedit(i_ctx_t *i_ctx_p) { uint count = 0; bool in_eol = false; int code; os_ptr op = osp; bool statement; stream *s; stream *ins; gs_string str; uint initial_buf_size; const char *filename; /* * buf exists only for stylistic parallelism: all occurrences of * buf-> could just as well be str. . */ gs_string *const buf = &str; check_type(*op, t_string); /* line assembled so far */ buf->data = op->value.bytes; buf->size = op->tas.rsize; check_type(*(op-1), t_integer); /* index */ count = (op-1)->value.intval; check_type(*(op-2), t_boolean); /* statementedit/lineedit */ statement = (op-2)->value.boolval; check_read_file(ins, op - 3); /* %stdin */ /* extend string */ initial_buf_size = statement ? STATEMENTEDIT_BUF_SIZE : LINEEDIT_BUF_SIZE; if (initial_buf_size > max_string_size) return_error(e_limitcheck); if (!buf->data || (buf->size < initial_buf_size)) { count = 0; buf->data = gs_alloc_string(imemory_system, initial_buf_size, "zfilelineedit(buffer)"); if (buf->data == 0) return_error(e_VMerror); op->value.bytes = buf->data; op->tas.rsize = buf->size = initial_buf_size; } rd: code = zreadline_from(ins, buf, imemory_system, &count, &in_eol); if (buf->size > max_string_size) { /* zreadline_from reallocated the buffer larger than * is valid for a PostScript string. * Return an error, but first realloc the buffer * back to a legal size. */ byte *nbuf = gs_resize_string(imemory_system, buf->data, buf->size, max_string_size, "zfilelineedit(shrink buffer)"); if (nbuf == 0) return_error(e_VMerror); op->value.bytes = buf->data = nbuf; op->tas.rsize = buf->size = max_string_size; return_error(e_limitcheck); } op->value.bytes = buf->data; /* zreadline_from sometimes resizes the buffer. */ op->tas.rsize = buf->size; switch (code) { case EOFC: code = gs_note_error(e_undefinedfilename); /* falls through */ case 0: break; default: code = gs_note_error(e_ioerror); break; case CALLC: { ref rfile; (op-1)->value.intval = count; /* callout is for stdin */ make_file(&rfile, a_readonly | avm_system, ins->read_id, ins); code = s_handle_read_exception(i_ctx_p, code, &rfile, NULL, 0, zfilelineedit); } break; case 1: /* filled buffer */ { uint nsize = buf->size; byte *nbuf; if (nsize >= max_string_size) { code = gs_note_error(e_limitcheck); break; } else if (nsize >= max_string_size / 2) nsize= max_string_size; else nsize = buf->size * 2; nbuf = gs_resize_string(imemory_system, buf->data, buf->size, nsize, "zfilelineedit(grow buffer)"); if (nbuf == 0) { code = gs_note_error(e_VMerror); break; } op->value.bytes = buf->data = nbuf; op->tas.rsize = buf->size = nsize; goto rd; } } if (code != 0) return code; if (statement) { /* If we don't have a complete token, keep going. */ stream st; stream *ts = &st; scanner_state state; ref ignore_value; uint depth = ref_stack_count(&o_stack); int code; /* Add a terminating EOL. */ if (count + 1 > buf->size) { uint nsize; byte *nbuf; nsize = buf->size + 1; if (nsize > max_string_size) { return_error(gs_note_error(e_limitcheck)); } else { nbuf = gs_resize_string(imemory_system, buf->data, buf->size, nsize, "zfilelineedit(grow buffer)"); if (nbuf == 0) { code = gs_note_error(e_VMerror); return_error(code); } op->value.bytes = buf->data = nbuf; op->tas.rsize = buf->size = nsize; } } buf->data[count++] = char_EOL; s_init(ts, NULL); sread_string(ts, buf->data, count); sc: scanner_init_stream_options(&state, ts, SCAN_CHECK_ONLY); code = scan_token(i_ctx_p, &ignore_value, &state); ref_stack_pop_to(&o_stack, depth); if (code < 0) code = scan_EOF; /* stop on scanner error */ switch (code) { case 0: /* read a token */ case scan_BOS: goto sc; /* keep going until we run out of data */ case scan_Refill: goto rd; case scan_EOF: break; default: /* error */ return code; } } buf->data = gs_resize_string(imemory_system, buf->data, buf->size, count, "zfilelineedit(resize buffer)"); if (buf->data == 0) return_error(e_VMerror); op->value.bytes = buf->data; op->tas.rsize = buf->size; s = file_alloc_stream(imemory_system, "zfilelineedit(stream)"); if (s == 0) return_error(e_VMerror); sread_string(s, buf->data, count); s->save_close = s->procs.close; s->procs.close = file_close_disable; filename = statement ? gs_iodev_statementedit.dname : gs_iodev_lineedit.dname; code = ssetfilename(s, (const byte *)filename, strlen(filename)+1); if (code < 0) { sclose(s); return_error(e_VMerror); } pop(3); make_stream_file(osp, s, "r"); return code; }