예제 #1
0
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;
}
예제 #2
0
/* <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;
}
예제 #3
0
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);
}
예제 #4
0
파일: zfsample.c 프로젝트: hackqiang/gs
/*
 * 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;
}
예제 #5
0
/*
 * 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);
}
예제 #6
0
파일: zdps1.c 프로젝트: ststeiger/ghostsvg
/* - 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;
}
예제 #7
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);
}
예제 #8
0
파일: zchar.c 프로젝트: ststeiger/ghostsvg
/* 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;
}
예제 #9
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;
}
예제 #10
0
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;
}