/* * Continuation for procedure data source. We use the topmost aliasing slot * to remember whether we've just called the procedure (1) or whether we're * returning from a RemapColor callout (0). */ static int image_proc_continue(i_ctx_t *i_ctx_p) { os_ptr op = osp; gs_image_enum *penum = r_ptr(esp, gs_image_enum); int px = ETOP_PLANE_INDEX(esp)->value.intval; int num_sources = ETOP_NUM_SOURCES(esp)->value.intval; uint size, used[gs_image_max_planes]; gs_const_string plane_data[gs_image_max_planes]; const byte *wanted; int i, code; if (!r_has_type_attrs(op, t_string, a_read)) { check_op(1); /* Procedure didn't return a (readable) string. Quit. */ esp = zimage_pop_estack(esp); image_cleanup(i_ctx_p); return_error(!r_has_type(op, t_string) ? e_typecheck : e_invalidaccess); } size = r_size(op); if (size == 0 && ETOP_SOURCE(esp, 0)[1].value.intval == 0) code = 1; else { for (i = 0; i < num_sources; i++) plane_data[i].size = 0; plane_data[px].data = op->value.bytes; plane_data[px].size = size; code = gs_image_next_planes(penum, plane_data, used); if (code == e_RemapColor) { op->value.bytes += used[px]; /* skip used data */ r_dec_size(op, used[px]); ETOP_SOURCE(esp, 0)[1].value.intval = 0; /* RemapColor callout */ return code; } } if (code) { /* Stop now. */ esp = zimage_pop_estack(esp); pop(1); image_cleanup(i_ctx_p); return (code < 0 ? code : o_pop_estack); } pop(1); wanted = gs_image_planes_wanted(penum); do { if (++px == num_sources) px = 0; } while (!wanted[px]); ETOP_PLANE_INDEX(esp)->value.intval = px; return image_proc_process(i_ctx_p); }
/* Process the next piece of an image. */ int gs_image_next(gs_image_enum * penum, const byte * dbytes, uint dsize, uint * pused) { int px = penum->plane_index; int num_planes = penum->num_planes; int i, code; uint used[GS_IMAGE_MAX_COMPONENTS]; gs_const_string plane_data[GS_IMAGE_MAX_COMPONENTS]; if (penum->planes[px].source.size != 0) return_error(gs_error_rangecheck); for (i = 0; i < num_planes; i++) plane_data[i].size = 0; plane_data[px].data = dbytes; plane_data[px].size = dsize; penum->error = false; code = gs_image_next_planes(penum, plane_data, used); *pused = used[px]; if (code >= 0) next_plane(penum); return code; }
/* This may still encounter a RemapColor callback. */ static int image_string_continue(i_ctx_t *i_ctx_p) { gs_image_enum *penum = r_ptr(esp, gs_image_enum); int num_sources = ETOP_NUM_SOURCES(esp)->value.intval; gs_const_string sources[gs_image_max_planes]; uint used[gs_image_max_planes]; /* Pass no data initially, to find out how much is retained. */ memset(sources, 0, sizeof(sources[0]) * num_sources); for (;;) { int px; int code = gs_image_next_planes(penum, sources, used); if (code == e_RemapColor) return code; stop_now: if (code) { /* Stop now. */ esp -= NUM_PUSH(num_sources); image_cleanup(i_ctx_p); return (code < 0 ? code : o_pop_estack); } for (px = 0; px < num_sources; ++px) if (sources[px].size == 0) { const ref *psrc = ETOP_SOURCE(esp, px); uint size = r_size(psrc); if (size == 0) { /* empty source */ code = 1; goto stop_now; } sources[px].data = psrc->value.bytes; sources[px].size = size; } } }
/* Continue processing data from an image with file data sources. */ static int image_file_continue(i_ctx_t *i_ctx_p) { gs_image_enum *penum = r_ptr(esp, gs_image_enum); int num_sources = ETOP_NUM_SOURCES(esp)->value.intval; for (;;) { uint min_avail = max_int; gs_const_string plane_data[gs_image_max_planes]; int code; int px; const ref *pp; bool at_eof = false; /* * Do a first pass through the files to ensure that at least * one has data available in its buffer. */ for (px = 0, pp = ETOP_SOURCE(esp, 0); px < num_sources; ++px, pp -= 2 ) { int num_aliases = pp[1].value.intval; stream *s = pp->value.pfile; int min_left; uint avail; if (num_aliases <= 0) num_aliases = ETOP_SOURCE(esp, -num_aliases)[1].value.intval; while ((avail = sbufavailable(s)) <= (min_left = sbuf_min_left(s)) + num_aliases - 1) { int next = s->end_status; switch (next) { case 0: s_process_read_buf(s); continue; case EOFC: at_eof = true; break; /* with no data available */ case INTC: case CALLC: return s_handle_read_exception(i_ctx_p, next, pp, NULL, 0, image_file_continue); default: /* case ERRC: */ return_error(e_ioerror); } break; /* for EOFC */ } /* * Note that in the EOF case, we can get here with no data * available. */ if (avail >= min_left) avail = (avail - min_left) / num_aliases; /* may be 0 */ if (avail < min_avail) min_avail = avail; plane_data[px].data = sbufptr(s); plane_data[px].size = avail; } /* * Now pass the available buffered data to the image processor. * Even if there is no available data, we must call * gs_image_next_planes one more time to finish processing any * retained data. */ { int pi; uint used[gs_image_max_planes]; code = gs_image_next_planes(penum, plane_data, used); /* Now that used has been set, update the streams. */ for (pi = 0, pp = ETOP_SOURCE(esp, 0); pi < num_sources; ++pi, pp -= 2 ) sbufskip(pp->value.pfile, used[pi]); if (code == e_RemapColor) return code; } if (at_eof) code = 1; if (code) { int code1; esp = zimage_pop_estack(esp); code1 = image_cleanup(i_ctx_p); return (code < 0 ? code : code1 < 0 ? code1 : o_pop_estack); } } }