/* 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; }
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; } } }