/* Common code for token reading + execution. */
static int
tokenexec_continue(i_ctx_t *i_ctx_p, scanner_state * pstate, bool save)
{
    os_ptr op;
    int code;
    /* Note that gs_scan_token may change osp! */
    pop(1);
again:
    check_estack(1);
    code = gs_scan_token(i_ctx_p, (ref *) (esp + 1), pstate);
    op = osp;
    switch (code) {
        case 0:
            if (r_is_proc(esp + 1)) {   /* Treat procedure as a literal. */
                push(1);
                ref_assign(op, esp + 1);
                code = 0;
                break;
            }
            /* falls through */
        case scan_BOS:
            ++esp;
            code = o_push_estack;
            break;
        case scan_EOF:          /* no tokens */
            code = 0;
            break;
        case scan_Refill:       /* need more data */
            code = gs_scan_handle_refill(i_ctx_p, pstate, save,
                                      ztokenexec_continue);
            switch (code) {
                case 0: /* state is not copied to the heap */
                    goto again;
                case o_push_estack:
                    return code;
            }
            break;              /* error */
        case scan_Comment:
        case scan_DSC_Comment:
            return ztoken_handle_comment(i_ctx_p, pstate, esp + 1, code,
                                         save, true, ztokenexec_continue);
        default:                /* error */
            gs_scanner_error_object(i_ctx_p, pstate, &i_ctx_p->error_object);
            break;
    }
    if (!save) {                /* Deallocate the scanner state record. */
        gs_free_object(((scanner_state_dynamic *)pstate)->mem, pstate, "token_continue");
    }
    return code;
}
Exemple #2
0
static int
zimage_data_setup(i_ctx_t *i_ctx_p, const gs_pixel_image_t * pim,
		  gx_image_enum_common_t * pie, const ref * sources, int npop)
{
    int num_sources = pie->num_planes;
    int inumpush = NUM_PUSH(num_sources);
    int code;
    gs_image_enum *penum;
    int px;
    const ref *pp;
    bool string_sources = true;

    check_estack(inumpush + 2);	/* stuff above, + continuation + proc */
    make_int(EBOT_NUM_SOURCES(esp), num_sources);
    /*
     * Note that the data sources may be procedures, strings, or (Level
     * 2 only) files.  (The Level 1 reference manual says that Level 1
     * requires procedures, but Adobe Level 1 interpreters also accept
     * strings.)  The sources must all be of the same type.
     *
     * The Adobe documentation explicitly says that if two or more of the
     * data sources are the same or inter-dependent files, the result is not
     * defined.  We don't have a problem with the bookkeeping for
     * inter-dependent files, since each one has its own buffer, but we do
     * have to be careful if two or more sources are actually the same file.
     * That is the reason for the aliasing information described above.
     */
    for (px = 0, pp = sources; px < num_sources; px++, pp++) {
	es_ptr ep = EBOT_SOURCE(esp, px);

	make_int(ep + 1, 1);	/* default is no aliasing */
	switch (r_type(pp)) {
	    case t_file:
		if (!level2_enabled)
		    return_error(e_typecheck);
		/* Check for aliasing. */
		{
		    int pi;

		    for (pi = 0; pi < px; ++pi)
			if (sources[pi].value.pfile == pp->value.pfile) {
			    /* Record aliasing */
			    make_int(ep + 1, -pi);
			    EBOT_SOURCE(esp, pi)[1].value.intval++;
			    break;
			}
		}
		string_sources = false;
		/* falls through */
	    case t_string:
		if (r_type(pp) != r_type(sources)) {
    		    if (pie != NULL)
		        gx_image_end(pie, false);    /* Clean up pie */
		    return_error(e_typecheck);
		}
		check_read(*pp);
		break;
	    default:
		if (!r_is_proc(sources)) {
    		    static const char ds[] = "DataSource";
                    if (pie != NULL)
                        gx_image_end(pie, false);    /* Clean up pie */
                    gs_errorinfo_put_pair(i_ctx_p, ds, sizeof(ds) - 1, pp);
		    return_error(e_typecheck);
		}
		check_proc(*pp);
		string_sources = false;
	}
	*ep = *pp;
    }
    /* Always place the image enumerator into local memory,
       because pie may have local objects inherited from igs,
       which may be local when the current allocation mode is global. 
       Bug 688140. */
    if ((penum = gs_image_enum_alloc(imemory_local, "image_setup")) == 0)
	return_error(e_VMerror);
    code = gs_image_enum_init(penum, pie, (const gs_data_image_t *)pim, igs);
    if (code != 0 || (pie->skipping && string_sources)) {		/* error, or empty image */
	int code1 = gs_image_cleanup_and_free_enum(penum, igs);

	if (code >= 0)		/* empty image */
	    pop(npop);
	if (code >= 0 && code1 < 0)
	    code = code1;
	return code;
    }
    push_mark_estack(es_other, image_cleanup);
    esp += inumpush - 1;
    make_int(ETOP_PLANE_INDEX(esp), 0);
    make_int(ETOP_NUM_SOURCES(esp), num_sources);
    make_struct(esp, avm_local, penum);
    switch (r_type(sources)) {
	case t_file:
	    push_op_estack(image_file_continue);
	    break;
	case t_string:
	    push_op_estack(image_string_continue);
	    break;
	default:		/* procedure */
	    push_op_estack(image_proc_process);
	    break;
    }
    pop(npop);
    return o_push_estack;
}
static int
charstring_execchar_aux(i_ctx_t *i_ctx_p, gs_text_enum_t *penum, gs_font *pfont)
{
    os_ptr op = osp;
    gs_font_base *const pbfont = (gs_font_base *) pfont;
    gs_font_type1 *const pfont1 = (gs_font_type1 *) pfont;
    const gs_type1_data *pdata;
    gs_type1exec_state cxs;
    gs_type1_state *const pcis = &cxs.cis;
    gs_rect FontBBox = pfont1->FontBBox;
    int code;

    if (penum->current_font->FontType == ft_CID_encrypted) {
        if (FontBBox.q.x <= FontBBox.p.x && FontBBox.q.y <= FontBBox.p.y) {
            gs_font_cid0 *pfcid0 = (gs_font_cid0 *)penum->current_font;

            FontBBox = pfcid0->FontBBox;
        }
    }

    pdata = &pfont1->data;
    /*
     * Any reasonable implementation would execute something like
     *    1 setmiterlimit 0 setlinejoin 0 setlinecap
     * here, but the Adobe implementations don't.
     *
     * If this is a stroked font, set the stroke width.
     */
    if (pfont->PaintType)
        gs_setlinewidth(igs, pfont->StrokeWidth);
    check_estack(3);		/* for continuations */
    /*
     * Execute the definition of the character.
     */
    if (r_is_proc(op))
        return zchar_exec_char_proc(i_ctx_p);
    /*
     * The definition must be a Type 1 CharString.
     * Note that we do not require read access: this is deliberate.
     */
    check_type(*op, t_string);
    if (r_size(op) <= max(pdata->lenIV, 0))
        return_error(e_invalidfont);
    /*
     * In order to make character oversampling work, we must
     * set up the cache before calling .type1addpath.
     * To do this, we must get the bounding box from the FontBBox,
     * and the width from the CharString or the Metrics.
     * If the FontBBox isn't valid, we can't do any of this.
     */

    if ((penum->FontBBox_as_Metrics2.x == 0 &&
         penum->FontBBox_as_Metrics2.y == 0) ||
        gs_rootfont(igs)->WMode == 0 ) {
        code = zchar_get_metrics(pbfont, op - 1, cxs.sbw);
        if (code < 0)
            return code;
        cxs.present = code;
        cxs.use_FontBBox_as_Metrics2 = false;
    }  else {  /* pass here if FontType==9,11 && WMode==1*/
        cxs.sbw[0] = penum->FontBBox_as_Metrics2.x / 2;
        cxs.sbw[1] = penum->FontBBox_as_Metrics2.y;
        cxs.sbw[2] = 0;
        cxs.sbw[3] = -penum->FontBBox_as_Metrics2.x; /* Sic! */
        cxs.use_FontBBox_as_Metrics2 = true;
        cxs.present = metricsNone;
    }
    /* Establish a current point. */
    code = gs_moveto(igs, 0.0, 0.0);
    if (code < 0)
        return code;
    code = type1_exec_init(pcis, penum, igs, pfont1);
    if (code < 0)
        return code;
    gs_type1_set_callback_data(pcis, &cxs);
    if (FontBBox.q.x > FontBBox.p.x &&
        FontBBox.q.y > FontBBox.p.y
        ) {
        /* The FontBBox appears to be valid. */
        op_proc_t exec_cont = 0;

        cxs.char_bbox = pfont1->FontBBox;
        code = type1exec_bbox(i_ctx_p, penum, &cxs, pfont, &exec_cont);
        if (code >= 0 && exec_cont != 0)
            code = (*exec_cont)(i_ctx_p);
        return code;
    } else {
        /* The FontBBox is not valid */
        const ref *opstr = op;
        ref other_subr;
        const gs_matrix * pctm = &ctm_only(igs);

        /* First, check for singular CTM */
        if (pctm->xx * pctm->yy == pctm->xy * pctm->yx) {
           /* The code below won't be able to find the FontBBox but we
            * don't need it anyway. Set an empty box and consider it valid.
            */
            op_proc_t exec_cont = 0;

            cxs.char_bbox.p.x = 0;
            cxs.char_bbox.p.y = 0;
            cxs.char_bbox.q.x = 0;
            cxs.char_bbox.q.y = 0;
            code = type1exec_bbox(i_ctx_p, penum, &cxs, pfont, &exec_cont);
            if (code >= 0 && exec_cont != 0)
                code = (*exec_cont)(i_ctx_p);
            return code;
        }
        /* Now we create the path first, then do the setcachedevice.
         * If we are oversampling (in this case, only for anti-
         * aliasing, not just to improve quality), we have to
         * create the path twice, since we can't know the
         * oversampling factor until after setcachedevice.
         */
        switch (cxs.present) {
            case metricsSideBearingAndWidth: {
                gs_point pt;

                pt.x = cxs.sbw[0], pt.y = cxs.sbw[1];
                gs_type1_set_lsb(pcis, &pt);
            }
            /* fall through */
            case metricsWidthOnly: {
                gs_point pt;

                pt.x = cxs.sbw[2], pt.y = cxs.sbw[3];
                gs_type1_set_width(pcis, &pt);
            }
        }

        /* Continue interpreting. */
      icont:
        code = type1_continue_dispatch(i_ctx_p, &cxs, opstr, &other_subr, 4);
        op = osp;		/* OtherSubrs might change it */
        switch (code) {
            case 0:		/* all done */
                return nobbox_finish(i_ctx_p, &cxs);
            default:		/* code < 0, error */
                return code;
            case type1_result_callothersubr:	/* unknown OtherSubr */
                return type1_call_OtherSubr(i_ctx_p, &cxs, nobbox_continue,
                                            &other_subr);
            case type1_result_sbw:	/* [h]sbw, just continue */
                switch (cxs.present) {
                    case metricsNone:
                        cxs.sbw[0] = fixed2float(pcis->lsb.x);
                        cxs.sbw[1] = fixed2float(pcis->lsb.y);
                    /* fall through */
                    case metricsWidthOnly:
                        cxs.sbw[2] = fixed2float(pcis->width.x);
                        cxs.sbw[3] = fixed2float(pcis->width.y);
                }
                opstr = 0;
                goto icont;
        }
    }
}