Example #1
0
static bool
charstring_is_notdef_proc(const gs_memory_t *mem, const ref *pcstr)
{
    if (r_is_array(pcstr) && r_size(pcstr) == 4) {
        ref elts[4];
        long i;

        for (i = 0; i < 4; ++i)
            array_get(mem, pcstr, i, &elts[i]);
        if (r_has_type(&elts[0], t_name) &&
            r_has_type(&elts[1], t_integer) && elts[1].value.intval == 0 &&
            r_has_type(&elts[2], t_integer) && elts[2].value.intval == 0 &&
            r_has_type(&elts[3], t_name)
            ) {
            ref nref;

            name_enter_string(mem, "pop", &nref);
            if (name_eq(&elts[0], &nref)) {
                name_enter_string(mem, "setcharwidth", &nref);
                if (name_eq(&elts[3], &nref))
                    return true;
            }
        }
    }
    return false;
}
Example #2
0
/* Call out to a PostScript procedure. */
static int
push_callout(i_ctx_t *i_ctx_p, const char *callout_name)
{
    int code;

    check_estack(1);
    code = name_enter_string(imemory, callout_name, esp + 1);
    if (code < 0)
        return code;
    ++esp;
    r_set_attrs(esp, a_executable);
    return o_push_estack;
}
Example #3
0
/* - .typenames <name1|null> ... <nameN|null> */
static int
ztypenames(i_ctx_t *i_ctx_p)
{
    os_ptr op = osp;
    static const char *const tnames[] = { REF_TYPE_NAME_STRINGS };
    int i;

    check_ostack(t_next_index);
    for (i = 0; i < t_next_index; i++) {
	ref *const rtnp = op + 1 + i;

	if (i >= countof(tnames) || tnames[i] == 0)
	    make_null(rtnp);
	else {
	    int code = name_enter_string(imemory, tnames[i], rtnp);

	    if (code < 0)
		return code;
	    r_set_attrs(rtnp, a_executable);
	}
    }
    osp += t_next_index;
    return 0;
}
Example #4
0
/* initialize the dictionaries that hold operator definitions. */
int
obj_init(i_ctx_t **pi_ctx_p, gs_dual_memory_t *idmem)
{
    int level = gs_op_language_level();
    ref system_dict;
    i_ctx_t *i_ctx_p;
    int code;

    /*
     * Create systemdict.  The context machinery requires that
     * we do this before initializing the interpreter.
     */
    code = dict_alloc(idmem->space_global,
		      (level >= 3 ? SYSTEMDICT_LL3_SIZE :
		       level >= 2 ? SYSTEMDICT_LEVEL2_SIZE : SYSTEMDICT_SIZE),
		      &system_dict);
    if (code < 0)
	return code;

    /* Initialize the interpreter. */
    code = gs_interp_init(pi_ctx_p, &system_dict, idmem);
    if (code < 0)
	return code;
    i_ctx_p = *pi_ctx_p;

    {
#define icount countof(initial_dictionaries)
	ref idicts[icount];
	int i;
	const op_def *const *tptr;

	min_dstack_size = MIN_DSTACK_SIZE;

	refset_null(idicts, icount);

	/* Put systemdict on the dictionary stack. */
	if (level >= 2) {
	    dsp += 2;
	    /*
	     * For the moment, let globaldict be an alias for systemdict.
	     */
	    dsp[-1] = system_dict;
	    min_dstack_size++;
	} else {
	    ++dsp;
	}
	*dsp = system_dict;

	/* Create dictionaries which are to be homes for operators. */
	for (tptr = op_defs_all; *tptr != 0; tptr++) {
	    const op_def *def;

	    for (def = *tptr; def->oname != 0; def++)
		if (op_def_is_begin_dict(def)) {
		    if (make_initial_dict(i_ctx_p, def->oname, idicts) == 0)
			return_error(e_VMerror);
		}
	}

	/* Set up the initial dstack. */
	for (i = 0; i < countof(initial_dstack); i++) {
	    const char *dname = initial_dstack[i];

	    ++dsp;
	    if (!strcmp(dname, "userdict"))
		dstack_userdict_index = dsp - dsbot;
	    ref_assign(dsp, make_initial_dict(i_ctx_p, dname, idicts));
	}

	/* Enter names of referenced initial dictionaries into systemdict. */
	initial_enter_name("systemdict", systemdict);
	for (i = 0; i < icount; i++) {
	    ref *idict = &idicts[i];

	    if (!r_has_type(idict, t_null)) {
		/*
		 * Note that we enter the dictionary in systemdict
		 * even if it is in local VM.  There is a special
		 * provision in the garbage collector for this:
		 * see ivmspace.h for more information.
		 * In order to do this, we must temporarily
		 * identify systemdict as local, so that the
		 * store check in dict_put won't fail.
		 */
		uint save_space = r_space(systemdict);

		r_set_space(systemdict, avm_local);
		code = initial_enter_name(initial_dictionaries[i].name,
					  idict);
		r_set_space(systemdict, save_space);
		if (code < 0)
		    return code;
	    }
	}
#undef icount
    }

    gs_interp_reset(i_ctx_p);

    {
	ref vnull, vtrue, vfalse;

	make_null(&vnull);
	make_true(&vtrue);
	make_false(&vfalse);
	if ((code = initial_enter_name("null", &vnull)) < 0 ||
	    (code = initial_enter_name("true", &vtrue)) < 0 ||
	    (code = initial_enter_name("false", &vfalse)) < 0
	    )
	    return code;
    }

    /* Create the error name table */
    {
	int n = countof(gs_error_names) - 1;
	int i;
	ref era;

	code = ialloc_ref_array(&era, a_readonly, n, "ErrorNames");
	if (code < 0)
	    return code;
	for (i = 0; i < n; i++)
	  if ((code = name_enter_string(imemory, (const char *)gs_error_names[i],
					  era.value.refs + i)) < 0)
		return code;
	return initial_enter_name("ErrorNames", &era);
    }
}
Example #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);
    }
}
Example #6
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;
}
Example #7
0
int
make_upath(i_ctx_t *i_ctx_p, ref *rupath, gs_state *pgs, gx_path *ppath,
           bool with_ucache)
{
    int size = (with_ucache ? 6 : 5);
    gs_path_enum penum;
    gs_rect bbox;
    int op;
    ref *next;
    int code;

    /* Compute the bounding box. */
    if ((code = gs_upathbbox(pgs, &bbox, true)) < 0) {
        /*
         * Note: Adobe throws 'nocurrentpoint' error, but the PLRM does
         * not list this as a possible error from 'upath', so if we are
         * not in CPSI compatibility mode, we set a reasonable default
         * bbox instead.
         */
        if (code != e_nocurrentpoint || gs_currentcpsimode(imemory))
            return code;
        bbox.p.x = bbox.p.y = bbox.q.x = bbox.q.y = 0;
    }

    code = path_length_for_upath(ppath);
    if (code < 0)
        return code;
    size += code;
    if (size >= 65536)
        return_error(e_limitcheck);

    code = ialloc_ref_array(rupath, a_all | a_executable, size,
                            "make_upath");
    if (code < 0)
        return code;
    /* Construct the path. */
    next = rupath->value.refs;
    if (with_ucache) {
        if ((code = name_enter_string(pgs->memory, "ucache", next)) < 0)
            return code;
        r_set_attrs(next, a_executable | l_new);
        ++next;
    }
    make_real_new(next, bbox.p.x);
    make_real_new(next + 1, bbox.p.y);
    make_real_new(next + 2, bbox.q.x);
    make_real_new(next + 3, bbox.q.y);
    next += 4;
    if ((code = name_enter_string(pgs->memory, "setbbox", next)) < 0)
        return code;
    r_set_attrs(next, a_executable | l_new);
    ++next;
    {
        gs_point pts[3];

        /* Patch the path in the gstate to set up the enumerator. */
        gx_path *save_path = pgs->path;

        pgs->path = ppath;
        gs_path_enum_copy_init(&penum, pgs, false);
        pgs->path = save_path;
        while ((op = gs_path_enum_next(&penum, pts)) != 0) {
            const char *opstr;

            switch (op) {
                case gs_pe_moveto:
                    opstr = "moveto";
                    goto ml;
                case gs_pe_lineto:
                    opstr = "lineto";
                  ml:make_real_new(next, pts[0].x);
                    make_real_new(next + 1, pts[0].y);
                    next += 2;
                    break;
                case gs_pe_curveto:
                    opstr = "curveto";
                    make_real_new(next, pts[0].x);
                    make_real_new(next + 1, pts[0].y);
                    make_real_new(next + 2, pts[1].x);
                    make_real_new(next + 3, pts[1].y);
                    make_real_new(next + 4, pts[2].x);
                    make_real_new(next + 5, pts[2].y);
                    next += 6;
                    break;
                case gs_pe_closepath:
                    opstr = "closepath";
                    break;
                default:
                    return_error(e_unregistered);
            }
            if ((code = name_enter_string(pgs->memory, opstr, next)) < 0)
                return code;
            r_set_attrs(next, a_executable);
            ++next;
        }
    }
    return 0;
}
Example #8
0
/* <dict> <string> .parse_dsc_comments <dict> <dsc code> */
static int
zparse_dsc_comments(i_ctx_t *i_ctx_p)
{
#define MAX_DSC_MSG_SIZE (DSC_LINE_LENGTH + 4)	/* Allow for %% and CR/LF */
    os_ptr const opString = osp;
    os_ptr const opDict = opString - 1;
    uint ssize;
    int comment_code, code;
    char dsc_buffer[MAX_DSC_MSG_SIZE + 2];
    const cmdlist_t *pCmdList = DSCcmdlist;
    const char * const *pBadList = BadCmdlist;
    ref * pvalue;
    CDSC * dsc_data = NULL;
    dict_param_list list;

    /*
     * Verify operand types and length of DSC comment string.  If a comment
     * is too long then we simply truncate it.  Russell's parser gets to
     * handle any errors that may result.  (Crude handling but the comment
     * is bad, so ...).
     */
    check_type(*opString, t_string);
    check_dict_write(*opDict);
    ssize = r_size(opString);
    if (ssize > MAX_DSC_MSG_SIZE)   /* need room for EOL + \0 */
        ssize = MAX_DSC_MSG_SIZE;
    /*
     * Pick up the comment string to be parsed.
     */
    memcpy(dsc_buffer, opString->value.bytes, ssize);
    dsc_buffer[ssize] = 0x0d;	    /* Russell wants a 'line end' */
    dsc_buffer[ssize + 1] = 0;	    /* Terminate string */
    /*
     * Skip data block comments (see comments in front of BadCmdList).
     */
    while (*pBadList && strncmp(*pBadList, dsc_buffer, strlen(*pBadList)))
        pBadList++;
    if (*pBadList) {		    /* If found in list, then skip comment */	
        comment_code = 0;	    /* Force NOP */
    }
    else {
        /*
         * Parse comments - use Russell Lang's DSC parser.  We need to get
         * data area for Russell Lang's parser.  Note: We have saved the
         * location of the data area for the parser in our DSC dict.
         */
        code = dict_find_string(opDict, dsc_dict_name, &pvalue);
	dsc_data = r_ptr(pvalue, dsc_data_t)->dsc_data_ptr;
        if (code < 0)
            return code;
        comment_code = dsc_scan_data(dsc_data, dsc_buffer, ssize + 1);
        if_debug1('%', "[%%].parse_dsc_comments: code = %d\n", comment_code);
	/*
	 * We ignore any errors from Russell's parser.  The only value that
	 * it will return for an error is -1 so there is very little information.
	 * We also do not want bad DSC comments to abort processing of an
	 * otherwise valid PS file.
	 */
        if (comment_code < 0)
	    comment_code = 0;
    }
    /*
     * Transfer data from DSC structure to postscript variables.
     * Look up proper handler in the local cmd decode list.
     */
    while (pCmdList->code && pCmdList->code != comment_code )
	pCmdList++;
    if (pCmdList->dsc_proc) {
	code = dict_param_list_write(&list, opDict, NULL, iimemory);
	if (code < 0)
	    return code;
	code = (pCmdList->dsc_proc)((gs_param_list *)&list, dsc_data);
	iparam_list_release(&list);
	if (code < 0)
	    return code;
    }

    /* Put DSC comment name onto operand stack (replace string). */

    return name_enter_string(imemory, pCmdList->comment_name, opString);
}