Esempio n. 1
0
/* Return the number of elements to pop (>0) if OK, <0 if error. */
static int
rect_get(local_rects_t * plr, os_ptr op, gs_memory_t *mem)
{
    int format, code;
    uint n, count;
    gs_rect *pr;
    double rv[4];

    switch (r_type(op)) {
	case t_array:
	case t_mixedarray:
	case t_shortarray:
	case t_string:
	    code = num_array_format(op);
	    if (code < 0)
		return code;
	    format = code;
	    count = num_array_size(op, format);
	    if (count % 4)
		return_error(e_typecheck);
	    count /= 4;
	    break;
	default:		/* better be 4 numbers */
	    code = num_params(op, 4, rv);
	    if (code < 0)
		return code;
	    plr->pr = plr->rl;
	    plr->count = 1;
	    plr->rl[0].q.x = (plr->rl[0].p.x = rv[0]) + rv[2];
	    plr->rl[0].q.y = (plr->rl[0].p.y = rv[1]) + rv[3];
	    return 4;
    }
    plr->count = count;
    if (count <= MAX_LOCAL_RECTS)
	pr = plr->rl;
    else {
	pr = (gs_rect *)gs_alloc_byte_array(mem, count, sizeof(gs_rect),
					    "rect_get");
	if (pr == 0)
	    return_error(e_VMerror);
    }
    plr->pr = pr;
    for (n = 0; n < count; n++, pr++) {
	ref rnum;
	int i;

	for (i = 0; i < 4; i++) {
	    code = num_array_get(mem, (const ref *)op, format,
				 (n << 2) + i, &rnum);
	    switch (code) {
		case t_integer:
		    rv[i] = rnum.value.intval;
		    break;
		case t_real:
		    rv[i] = rnum.value.realval;
		    break;
		default:	/* code < 0 */
		    return code;
	    }
	}
	pr->q.x = (pr->p.x = rv[0]) + rv[2];
	pr->q.y = (pr->p.y = rv[1]) + rv[3];
    }
    return 1;
}
Esempio n. 2
0
/* Append a user path to the current path. */
static inline int
upath_append_aux(os_ptr oppath, i_ctx_t *i_ctx_p, int *pnargs, bool upath_compat)
{
    upath_state ups = UPS_INITIAL;
    ref opcodes;

    if (r_has_type(oppath, t__invalid))
        return_error(e_stackunderflow);
    if (!r_is_array(oppath))
        return_error(e_typecheck);
    check_read(*oppath);
    gs_newpath(igs);
    /****** ROUND tx AND ty ******/

    if ( r_size(oppath) == 2 &&
         array_get(imemory, oppath, 1, &opcodes) >= 0 &&
         r_has_type(&opcodes, t_string)
        ) {			/* 1st element is operands, 2nd is operators */
        ref operands;
        int code, format;
        int repcount = 1;
        const byte *opp;
        uint ocount, i = 0;

        array_get(imemory, oppath, 0, &operands);
        code = num_array_format(&operands);
        if (code < 0)
            return code;
        format = code;
        check_read(opcodes);
        opp = opcodes.value.bytes;
        ocount = r_size(&opcodes);
        while (ocount--) {
            byte opx = *opp++;

            if (opx > UPATH_REPEAT)
                repcount = opx - UPATH_REPEAT;
            else if (opx > UPATH_MAX_OP)
                return_error(e_rangecheck);
            else {		/* operator */
                const up_data_t data = up_data[opx];

                *pnargs = 0;	/* in case of error */
                if (upath_compat && opx == upath_op_ucache) {
                    /* CPSI does not complain about incorrect ucache
                       placement, even though PLRM3 says it's illegal. */
                    ups = ups > UPS_UCACHE ? ups : data.state_after;
                } else {
                    if (!(ups & data.states_before))
                        return_error(e_typecheck);
                    ups = data.state_after;
                }
                do {
                    os_ptr op = osp;
                    byte opargs = data.num_args;

                    while (opargs--) {
                        push(1);
                        (*pnargs)++; /* in case of error */
                        code = num_array_get(imemory, &operands, format, i++, op);
                        switch (code) {
                            case t_integer:
                                r_set_type_attrs(op, t_integer, 0);
                                break;
                            case t_real:
                                r_set_type_attrs(op, t_real, 0);
                                break;
                            default:
                                return_error(e_typecheck);
                        }
                    }
                    code = (*up_ops[opx])(i_ctx_p);
                    if (code < 0)
                        return code;
                }
                while (--repcount);
                repcount = 1;
            }
        }
    } else {	/* Ordinary executable array. */
        const ref *arp = oppath;
        uint ocount = r_size(oppath);
        long index = 0;
        int argcount = 0;
        op_proc_t oproc;
        int opx, code;

        for (; index < ocount; index++) {
            ref rup;
            ref *defp;
            os_ptr op = osp;
            up_data_t data;

            *pnargs = argcount;
            array_get(imemory, arp, index, &rup);
            switch (r_type(&rup)) {
                case t_integer:
                case t_real:
                    argcount++;
                    push(1);
                    *op = rup;
                    break;
                case t_name:
                    if (!r_has_attr(&rup, a_executable) ||
                        dict_find(systemdict, &rup, &defp) <= 0 ||
                        r_btype(defp) != t_operator)
                        return_error(e_typecheck); /* all errors = typecheck */
                    goto xop;
                case t_operator:
                    defp = &rup;
                  xop:if (!r_has_attr(defp, a_executable))
                        return_error(e_typecheck);
                    oproc = real_opproc(defp);
                    for (opx = 0; opx <= UPATH_MAX_OP; opx++)
                        if (oproc == up_ops[opx])
                            break;
                    if (opx > UPATH_MAX_OP)
                        return_error(e_typecheck);
                    data = up_data[opx];
                    if (argcount != data.num_args)
                        return_error(e_typecheck);
                    if (upath_compat && opx == upath_op_ucache) {
                        /* CPSI does not complain about incorrect ucache
                           placement, even though PLRM3 says it's illegal. */
                        ups = ups > UPS_UCACHE ? ups : data.state_after;
                    } else {
                        if (!(ups & data.states_before))
                            return_error(e_typecheck);
                        ups = data.state_after;
                    }
                    code = (*up_ops[opx])(i_ctx_p);
                    if (code < 0) {
                        if (code == e_nocurrentpoint)
                            return_error(e_rangecheck); /* CET 11-22 */
                        return code;
                    }
                    argcount = 0;
                    break;
                default:
                    return_error(e_typecheck);
            }
        }
        if (argcount) {
            *pnargs = argcount;
            return_error(e_typecheck);	/* leftover args */
        }
    }
    if (ups < UPS_SETBBOX)
        return_error(e_typecheck);	/* no setbbox */
    if (ups == UPS_SETBBOX && upath_compat) {
        /*
         * In CPSI compatibility mode, an empty path with a setbbox also
         * does a moveto (but only if the path is empty).  Since setbbox
         * was the last operator, its operands are still on the o-stack.
         */
        osp += 2;
        return zmoveto(i_ctx_p);
    }
    return 0;
}
Esempio n. 3
0
/* <string> <numarray|numstring> xyshow - */
static int
moveshow(i_ctx_t *i_ctx_p, bool have_x, bool have_y)
{
    os_ptr op = osp;
    gs_text_enum_t *penum = NULL;
    int code = op_show_setup(i_ctx_p, op - 1);
    int format;
    uint i, size, widths_needed;
    float *values;
    bool CPSI_mode = gs_currentcpsimode(imemory);

    if (code != 0)
        return code;
    format = num_array_format(op);
    if (format < 0)
        return format;
    size = num_array_size(op, format);
    values = (float *)ialloc_byte_array(size, sizeof(float), "moveshow");
    if (values == 0)
        return_error(gs_error_VMerror);
    if (CPSI_mode)
        memset(values, 0, size * sizeof(values[0])); /* Safety. */
    if ((code = gs_xyshow_begin(igs, op[-1].value.bytes, r_size(op - 1),
                                (have_x ? values : (float *)0),
                                (have_y ? values : (float *)0),
                                size, imemory_local, &penum)) < 0) {
        ifree_object(values, "moveshow");
        if (penum)	/* if there was an error, the text_enum may not have been allocated */
            penum->text.x_widths = penum->text.y_widths = NULL;
        return code;
    }
    if (CPSI_mode) {
        /* CET 13-29.PS page 2 defines a longer width array
           then the text requires, and CPSI silently ignores extra elements.
           So we need to compute exact number of characters
           to know how many elements to load and type check. */
        code = gs_text_count_chars(igs, gs_get_text_params(penum), imemory);
        if (code < 0)
            return code;
        widths_needed = code;
        if (have_x && have_y)
            widths_needed <<= 1;
    } else
        widths_needed = size;
    for (i = 0; i < widths_needed; ++i) {
        ref value;

        switch (code = num_array_get(imemory, op, format, i, &value)) {
        case t_integer:
            values[i] = (float)value.value.intval; break;
        case t_real:
            values[i] = value.value.realval; break;
        case t_null:
            code = gs_note_error(gs_error_rangecheck);
            /* falls through */
        default:
            ifree_object(values, "moveshow");
        penum->text.x_widths = penum->text.y_widths = NULL;
            return code;
        }
    }
    if ((code = op_show_finish_setup(i_ctx_p, penum, 2, NULL)) < 0) {
        ifree_object(values, "moveshow");
        penum->text.x_widths = penum->text.y_widths = NULL;
        return code;
    }
    pop(2);
    return op_show_continue(i_ctx_p);
}