Beispiel #1
0
/* Set up the next sample */
static int
screen_sample(i_ctx_t *i_ctx_p)
{
    os_ptr op = osp;
    gs_screen_enum *penum = senum;
    gs_point pt;
    int code = gs_screen_currentpoint(penum, &pt);
    ref proc;

    switch (code) {
        default:
            return code;
        case 1:
            /* All done */
            if (real_opproc(esp - 2) != 0)
                code = (*real_opproc(esp - 2)) (i_ctx_p);
            esp -= snumpush;
            screen_cleanup(i_ctx_p);
            return (code < 0 ? code : o_pop_estack);
        case 0:
            ;
    }
    push(2);
    make_real(op - 1, pt.x);
    make_real(op, pt.y);
    proc = sproc;
    push_op_estack(set_screen_continue);
    *++esp = proc;
    return o_push_estack;
}
Beispiel #2
0
static int
zforall(i_ctx_t *i_ctx_p)
{
    os_ptr op = osp;
    os_ptr obj = op - 1;
    es_ptr ep = esp;
    es_ptr cproc = ep + 4;

    check_estack(6);
    check_proc(*op);
    switch (r_type(obj)) {
	default:
	    return_op_typecheck(obj);
	case t_array:
	    check_read(*obj);
	    make_op_estack(cproc, array_continue);
	    break;
	case t_dictionary:
	    check_dict_read(*obj);
	    make_int(cproc, dict_first(obj));
	    ++cproc;
	    make_op_estack(cproc, dict_continue);
	    break;
	case t_string:
	    check_read(*obj);
	    make_op_estack(cproc, string_continue);
	    break;
	case t_mixedarray:
	case t_shortarray:
	    check_read(*obj);
	    make_op_estack(cproc, packedarray_continue);
	    break;
    }
    /*
     * Push:
     *   - a mark;
     *   - the composite object;
     *   - the procedure;
     *   - the iteration index (only for dictionaries, done above);
     * and invoke the continuation operator.
     */
    make_mark_estack(ep + 1, es_for, forall_cleanup);
    ep[2] = *obj;
    ep[3] = *op;
    esp = cproc - 1;
    pop(2);
    return (*real_opproc(cproc))(i_ctx_p);
}
Beispiel #3
0
/* Find the index of an operator that doesn't have one stored in it. */
ushort
op_find_index(const ref * pref /* t_operator */ )
{
    op_proc_t proc = real_opproc(pref);
    const op_def *const *opp = op_defs_all;
    const op_def *const *opend = opp + (op_def_count / OP_DEFS_MAX_SIZE);

    for (; opp < opend; ++opp) {
	const op_def *def = *opp;

	for (; def->oname != 0; ++def)
	    if (def->proc == proc)
		return (opp - op_defs_all) * OP_DEFS_MAX_SIZE + (def - *opp);
    }
    /* Lookup failed!  This isn't possible.... */
    return 0;
}
/*
 * Pop the e-stack, executing cleanup procedures as needed.
 * We could make this more efficient using ref_stack_enum_*,
 * but it isn't used enough to make this worthwhile.
 */
void
pop_estack(i_ctx_t *i_ctx_p, uint count)
{
    uint idx = 0;
    uint popped = 0;

    esfile_clear_cache();
    for (; idx < count; idx++) {
        ref *ep = ref_stack_index(&e_stack, idx - popped);

        if (r_is_estack_mark(ep)) {
            ref_stack_pop(&e_stack, idx + 1 - popped);
            popped = idx + 1;
            (*real_opproc(ep)) (i_ctx_p);
        }
    }
    ref_stack_pop(&e_stack, count - popped);
}
Beispiel #5
0
/*
 * Note that op_show_continue_dispatch sets osp = op explicitly iff the
 * dispatch succeeds.  This is so that the show operators don't pop anything
 * from the o-stack if they don't succeed.  Note also that if it returns an
 * error, it has freed the enumerator.
 */
int
op_show_continue_dispatch(i_ctx_t *i_ctx_p, int npop, int code)
{
    os_ptr op = osp - npop;
    gs_text_enum_t *penum = senum;

    switch (code) {
	case 0: {		/* all done */
	    os_ptr save_osp = osp;

	    osp = op;
	    code = (*real_opproc(&seproc)) (i_ctx_p);
	    op_show_free(i_ctx_p, code);
	    if (code < 0) {
		osp = save_osp;
		return code;
	    }
	    return o_pop_estack;
	}
	case TEXT_PROCESS_INTERVENE: {
	    ref *pslot = &sslot; /* only used for kshow */

	    push(2);
	    make_int(op - 1, gs_text_current_char(penum)); /* previous char */
	    make_int(op, gs_text_next_char(penum));
	    push_op_estack(op_show_continue);	/* continue after kerning */
	    *++esp = *pslot;	/* kerning procedure */
	    return o_push_estack;
	}
	case TEXT_PROCESS_RENDER: {
	    gs_font *pfont = gs_currentfont(igs);
	    font_data *pfdata = pfont_data(pfont);
	    gs_char chr = gs_text_current_char(penum);
	    gs_glyph glyph = gs_text_current_glyph(penum);

	    push(2);
	    op[-1] = pfdata->dict;	/* push the font */
	    /*
	     * For Type 1 and Type 4 fonts, prefer BuildChar to BuildGlyph
	     * if there is no glyph, or if there is both a character and a
	     * glyph and the glyph is the one that corresponds to the
	     * character in the Encoding, so that PostScript procedures
	     * appearing in the CharStrings dictionary will receive the
	     * character code rather than the character name; for Type 3
	     * fonts, prefer BuildGlyph to BuildChar.  For other font types
	     * (such as CID fonts), only BuildGlyph will be present.
	     */
	    if (pfont->FontType == ft_user_defined) {
		/* Type 3 font, prefer BuildGlyph. */
		if (level2_enabled &&
		    !r_has_type(&pfdata->BuildGlyph, t_null) &&
		    glyph != gs_no_glyph
		    ) {
		    glyph_ref(imemory, glyph, op);
		    esp[2] = pfdata->BuildGlyph;
		} else if (r_has_type(&pfdata->BuildChar, t_null))
		    goto err;
		else if (chr == gs_no_char) {
		    /* glyphshow, reverse map the character */
		    /* through the Encoding */
		    ref gref;
		    const ref *pencoding = &pfdata->Encoding;

		    glyph_ref(imemory, glyph, &gref);
		    if (!map_glyph_to_char(imemory, &gref, pencoding,
					   (ref *) op)
			) {	/* Not found, try .notdef */
		        name_enter_string(imemory, ".notdef", &gref);
			if (!map_glyph_to_char(imemory, &gref,
					       pencoding,
					       (ref *) op)
			    )
			    goto err;
		    }
		    esp[2] = pfdata->BuildChar;
		} else {
		    make_int(op, chr & 0xff);
		    esp[2] = pfdata->BuildChar;
		}
	    } else {
		/*
		 * For a Type 1 or Type 4 font, prefer BuildChar or
		 * BuildGlyph as described above: we know that both
		 * BuildChar and BuildGlyph are present.  For other font
		 * types, only BuildGlyph is available.
		 */
		ref eref, gref;

		if (chr != gs_no_char &&
		    !r_has_type(&pfdata->BuildChar, t_null) &&
		    (glyph == gs_no_glyph ||
		     (!r_has_type(&pfdata->Encoding, t_null) &&
		       array_get(imemory, &pfdata->Encoding, (long)(chr & 0xff), &eref) >= 0 &&
		      (glyph_ref(imemory, glyph, &gref), obj_eq(imemory, &gref, &eref))))
		    ) {
		    make_int(op, chr & 0xff);
		    esp[2] = pfdata->BuildChar;
		} else {
		    /* We might not have a glyph: substitute 0. **HACK** */
		    if (glyph == gs_no_glyph)
			make_int(op, 0);
		    else
		        glyph_ref(imemory, glyph, op);
		    esp[2] = pfdata->BuildGlyph;
		}
	    }
	    /* Save the stack depths in case we bail out. */
	    sodepth.value.intval = ref_stack_count(&o_stack) - 2;
	    sddepth.value.intval = ref_stack_count(&d_stack);
	    push_op_estack(op_show_continue);
	    ++esp;		/* skip BuildChar or BuildGlyph proc */
	    return o_push_estack;
	}
	case TEXT_PROCESS_CDEVPROC:
	    {   gs_font *pfont = penum->current_font;
		ref cnref;
		op_proc_t cont = op_show_continue, exec_cont = 0;
		gs_glyph glyph = penum->returned.current_glyph;
		int code;
    
		pop(npop);
		op = osp;
		glyph_ref(imemory, glyph, &cnref);
		if (pfont->FontType == ft_CID_TrueType) {
		    gs_font_type42 *pfont42 = (gs_font_type42 *)pfont;
		    uint glyph_index = pfont42->data.get_glyph_index(pfont42, glyph);

		    code = zchar42_set_cache(i_ctx_p, (gs_font_base *)pfont42, 
				    &cnref, glyph_index, cont, &exec_cont);
		} else if (pfont->FontType == ft_CID_encrypted)
		    code = z1_set_cache(i_ctx_p, (gs_font_base *)pfont, 
				    &cnref, glyph, cont, &exec_cont);
		else
		    return_error(e_unregistered); /* Unimplemented. */
		if (exec_cont != 0)
		    return_error(e_unregistered); /* Must not happen. */
		return code;
	    }
	default:		/* error */
err:
	    if (code >= 0)
		code = gs_note_error(e_invalidfont);
	    return op_show_free(i_ctx_p, code);
    }
}
Beispiel #6
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;
}