/* <bytestring1> <index> <string2> putinterval - */ static int zputinterval(i_ctx_t *i_ctx_p) { os_ptr op = osp; os_ptr opindex = op - 1; os_ptr opto = opindex - 1; int code; switch (r_type(opto)) { default: return_error(e_typecheck); case t__invalid: if (r_type(op) != t_array && r_type(op) != t_string && r_type(op) != t__invalid) return_error(e_typecheck); /* to match Distiller */ else return_error(e_stackunderflow); case t_mixedarray: case t_shortarray: return_error(e_invalidaccess); case t_array: case t_string: check_write(*opto); check_int_leu(*opindex, r_size(opto)); code = copy_interval(i_ctx_p, opto, (uint)(opindex->value.intval), op, "putinterval"); break; case t_astruct: { uint dsize, ssize, index; check_write(*opto); if (gs_object_type(imemory, opto->value.pstruct) != &st_bytes) return_error(e_typecheck); dsize = gs_object_size(imemory, opto->value.pstruct); check_int_leu(*opindex, dsize); index = (uint)opindex->value.intval; check_read_type(*op, t_string); ssize = r_size(op); if (ssize > dsize - index) return_error(e_rangecheck); memcpy(r_ptr(opto, byte) + index, op->value.const_bytes, ssize); code = 0; break; } } if (code >= 0) pop(3); return code; }
/* <mark> <size> <lower> <upper> setcacheparams - */ static int zsetcacheparams(i_ctx_t *i_ctx_p) { os_ptr op = osp; uint params[3]; int i, code; os_ptr opp = op; for (i = 0; i < 3 && !r_has_type(opp, t_mark); i++, opp--) { check_int_leu(*opp, max_uint); params[i] = opp->value.intval; } switch (i) { case 3: if ((code = gs_setcachesize(igs, ifont_dir, params[2])) < 0) return code; case 2: if ((code = gs_setcachelower(ifont_dir, params[1])) < 0) return code; case 1: if ((code = gs_setcacheupper(ifont_dir, params[0])) < 0) return code; case 0:; } return zcleartomark(i_ctx_p); }
/* <destx> <desty> <width> <height> <op> compositerect - */ static int zcompositerect(i_ctx_t *i_ctx_p) { os_ptr op = osp; double dest_rect[4]; alpha_composite_state_t cstate; int code = xywh_param(op - 1, dest_rect); if (code < 0) return code; check_int_leu(*op, compositerect_last); cstate.params.op = (gs_composite_op_t) op->value.intval; code = begin_composite(i_ctx_p, &cstate); if (code < 0) return code; { gs_rect rect; rect.q.x = (rect.p.x = dest_rect[0]) + dest_rect[2]; rect.q.y = (rect.p.y = dest_rect[1]) + dest_rect[3]; code = gs_rectfill(igs, &rect, 1); } end_composite(i_ctx_p, &cstate); if (code >= 0) pop(5); return code; }
/* Get an integer parameter in a given range. */ int int_param(const ref * op, int max_value, int *pparam) { check_int_leu(*op, max_value); *pparam = (int)op->value.intval; return 0; }
/* <obj1> ... <objn> <n> .execn - */ static int zexecn(i_ctx_t *i_ctx_p) { os_ptr op = osp; uint n, i; es_ptr esp_orig; check_int_leu(*op, max_uint - 1); n = (uint) op->value.intval; check_op(n + 1); check_estack(n); esp_orig = esp; for (i = 0; i < n; ++i) { const ref *rp = ref_stack_index(&o_stack, (long)(i + 1)); /* Make sure this object is legal to execute. */ if (ref_type_uses_access(r_type(rp))) { if (!r_has_attr(rp, a_execute) && r_has_attr(rp, a_executable) ) { esp = esp_orig; return_error(e_invalidaccess); } } /* Executable nulls have a special meaning on the e-stack, */ /* so since they are no-ops, don't push them. */ if (!r_has_type_attrs(rp, t_null, a_executable)) { ++esp; ref_assign(esp, rp); } } esfile_check_cache(); pop(n + 1); return o_push_estack; }
/* <seq:array|packedarray|string> <index> <count> getinterval <subseq> */ static int zgetinterval(i_ctx_t *i_ctx_p) { os_ptr op = osp; os_ptr op1 = op - 1; os_ptr op2 = op1 - 1; uint index; uint count; switch (r_type(op2)) { default: return_op_typecheck(op2); case t_array: case t_string: case t_mixedarray: case t_shortarray:; } check_read(*op2); check_int_leu(*op1, r_size(op2)); index = op1->value.intval; check_int_leu(*op, r_size(op2) - index); count = op->value.intval; switch (r_type(op2)) { case t_array: op2->value.refs += index; break; case t_string: op2->value.bytes += index; break; case t_mixedarray: { const ref_packed *packed = op2->value.packed; for (; index--;) packed = packed_next(packed); op2->value.packed = packed; break; } case t_shortarray: op2->value.packed += index; break; } r_set_size(op2, count); pop(2); return 0; }
/* <blimit> setcachelimit - */ static int zsetcachelimit(i_ctx_t *i_ctx_p) { os_ptr op = osp; check_int_leu(*op, max_uint); gs_setcachelimit(ifont_dir, (uint) op->value.intval); pop(1); return 0; }
/* composite - */ static int zcomposite(i_ctx_t *i_ctx_p) { os_ptr op = osp; gs_composite_alpha_params_t params; check_int_leu(*op, composite_last); params.op = (gs_composite_op_t) op->value.intval; return composite_image(i_ctx_p, ¶ms); }
/* <string> <index> <int> put - */ static int zput(i_ctx_t *i_ctx_p) { os_ptr op = osp; os_ptr op1 = op - 1; os_ptr op2 = op1 - 1; byte *sdata; uint ssize; switch (r_type(op2)) { case t_dictionary: if (i_ctx_p->in_superexec == 0) check_dict_write(*op2); { int code = idict_put(op2, op1, op); if (code < 0) return code; /* error */ } break; case t_array: check_write(*op2); check_int_ltu(*op1, r_size(op2)); store_check_dest(op2, op); { ref *eltp = op2->value.refs + (uint) op1->value.intval; ref_assign_old(op2, eltp, op, "put"); } break; case t_mixedarray: /* packed arrays are read-only */ case t_shortarray: return_error(e_invalidaccess); case t_string: sdata = op2->value.bytes; ssize = r_size(op2); str: check_write(*op2); check_int_ltu(*op1, ssize); check_int_leu(*op, 0xff); sdata[(uint)op1->value.intval] = (byte)op->value.intval; break; case t_astruct: if (gs_object_type(imemory, op2->value.pstruct) != &st_bytes) return_error(e_typecheck); sdata = r_ptr(op2, byte); ssize = gs_object_size(imemory, op2->value.pstruct); goto str; default: return_op_typecheck(op2); } pop(3); return 0; }
/* <int> array <array> */ int zarray(i_ctx_t *i_ctx_p) { os_ptr op = osp; uint size; int code; check_int_leu(*op, max_array_size); size = op->value.intval; code = ialloc_ref_array((ref *)op, a_all, size, "array"); if (code < 0) return code; refset_null(op->value.refs, size); return 0; }
/* <int> string <string> */ int zstring(i_ctx_t *i_ctx_p) { os_ptr op = osp; byte *sbody; uint size; check_int_leu(*op, max_string_size); size = op->value.intval; sbody = ialloc_string(size, "string"); if (sbody == 0) return_error(e_VMerror); make_string(op, a_all | icurrent_space, size, sbody); memset(sbody, 0, size); return 0; }
/* <int> .bytestring <bytestring> */ private int zbytestring(i_ctx_t *i_ctx_p) { os_ptr op = osp; byte *sbody; uint size; check_int_leu(*op, max_int); size = (uint)op->value.intval; sbody = ialloc_bytes(size, ".bytestring"); if (sbody == 0) return_error(e_VMerror); make_astruct(op, a_all | icurrent_space, sbody); memset(sbody, 0, size); return 0; }
/* [<req_x> <req_y>] [<med_x0> <med_y0> (<med_x1> <med_y1> | )] * <policy> <orient|null> <roll> <matrix|null> .matchpagesize * <matrix|null> <med_x> <med_y> true -or- false */ static int zmatchpagesize(i_ctx_t *i_ctx_p) { os_ptr op = osp; gs_matrix mat; float ignore_mismatch = (float)max_long; gs_point media_size; int orient; bool roll; int code; check_type(op[-3], t_integer); if (r_has_type(op - 2, t_null)) orient = -1; else { check_int_leu(op[-2], 3); orient = (int)op[-2].value.intval; } check_type(op[-1], t_boolean); roll = op[-1].value.boolval; code = zmatch_page_size(imemory, op - 5, op - 4, (int)op[-3].value.intval, orient, roll, &ignore_mismatch, &mat, &media_size); switch (code) { default: return code; case 0: make_false(op - 5); pop(5); break; case 1: code = write_matrix(op, &mat); if (code < 0 && !r_has_type(op, t_null)) return code; op[-5] = *op; make_real(op - 4, media_size.x); make_real(op - 3, media_size.y); make_true(op - 2); pop(2); break; } return 0; }
/* Common setup for glyphshow and .glyphwidth. */ static int glyph_show_setup(i_ctx_t *i_ctx_p, gs_glyph *pglyph) { os_ptr op = osp; switch (gs_currentfont(igs)->FontType) { case ft_CID_encrypted: case ft_CID_user_defined: case ft_CID_TrueType: case ft_CID_bitmap: check_int_leu(*op, gs_max_glyph - gs_min_cid_glyph); *pglyph = (gs_glyph) op->value.intval + gs_min_cid_glyph; break; default: check_type(*op, t_name); *pglyph = name_index(imemory, op); } return op_show_enum_setup(i_ctx_p); }
/* .getbitsrect <height> <substring> */ static int zgetbitsrect(i_ctx_t *i_ctx_p) { /* * alpha? is 0 for no alpha, -1 for alpha first, 1 for alpha last. * std_depth is null for native pixels, depth/component for * standard color space. */ os_ptr op = osp; gx_device *dev; gs_int_rect rect; gs_get_bits_params_t params; int w, h; gs_get_bits_options_t options = GB_ALIGN_ANY | GB_RETURN_COPY | GB_OFFSET_0 | GB_RASTER_STANDARD | GB_PACKING_CHUNKY; int depth; uint raster; int num_rows; int code; check_read_type(op[-7], t_device); dev = op[-7].value.pdevice; check_int_leu(op[-6], dev->width); rect.p.x = op[-6].value.intval; check_int_leu(op[-5], dev->height); rect.p.y = op[-5].value.intval; check_int_leu(op[-4], dev->width); w = op[-4].value.intval; check_int_leu(op[-3], dev->height); h = op[-3].value.intval; check_type(op[-2], t_integer); /* * We use if/else rather than switch because the value is long, * which is not supported as a switch value in pre-ANSI C. */ if (op[-2].value.intval == -1) options |= GB_ALPHA_FIRST; else if (op[-2].value.intval == 0) options |= GB_ALPHA_NONE; else if (op[-2].value.intval == 1) options |= GB_ALPHA_LAST; else return_error(e_rangecheck); if (r_has_type(op - 1, t_null)) { options |= GB_COLORS_NATIVE; depth = dev->color_info.depth; } else { static const gs_get_bits_options_t depths[17] = { 0, GB_DEPTH_1, GB_DEPTH_2, 0, GB_DEPTH_4, 0, 0, 0, GB_DEPTH_8, 0, 0, 0, GB_DEPTH_12, 0, 0, 0, GB_DEPTH_16 }; gs_get_bits_options_t depth_option; int std_depth; check_int_leu(op[-1], 16); std_depth = (int)op[-1].value.intval; depth_option = depths[std_depth]; if (depth_option == 0) return_error(e_rangecheck); options |= depth_option | GB_COLORS_NATIVE; depth = (dev->color_info.num_components + (options & GB_ALPHA_NONE ? 0 : 1)) * std_depth; } if (w == 0) return_error(e_rangecheck); raster = (w * depth + 7) >> 3; check_write_type(*op, t_string); num_rows = r_size(op) / raster; h = min(h, num_rows); if (h == 0) return_error(e_rangecheck); rect.q.x = rect.p.x + w; rect.q.y = rect.p.y + h; params.options = options; params.data[0] = op->value.bytes; code = (*dev_proc(dev, get_bits_rectangle))(dev, &rect, ¶ms, NULL); if (code < 0) return code; make_int(op - 7, h); op[-6] = *op; r_set_size(op - 6, h * raster); pop(6); return 0; }
/* <bitmap> <cid> <type32font> <str22> .makeglyph32 <<same with substr>> */ static int zmakeglyph32(i_ctx_t *i_ctx_p) { os_ptr op = osp; bool long_form; uint msize; double metrics[10]; int wx, llx, lly, urx, ury; int width, height, raster; gs_font *pfont; int code; byte *str; check_array(op[-4]); msize = r_size(op - 4); switch (msize) { case 10: long_form = true; break; case 6: long_form = false; break; default: return_error(gs_error_rangecheck); } code = num_params(op[-4].value.refs + msize - 1, msize, metrics); if (code < 0) return code; if (~code & 0x3c) /* check llx .. ury for integers */ return_error(gs_error_typecheck); check_read_type(op[-3], t_string); llx = (int)metrics[2]; lly = (int)metrics[3]; urx = (int)metrics[4]; ury = (int)metrics[5]; width = urx - llx; height = ury - lly; raster = (width + 7) >> 3; if (width < 0 || height < 0 || r_size(op - 3) != raster * height) return_error(gs_error_rangecheck); check_int_leu(op[-2], 65535); code = font_param(op - 1, &pfont); if (code < 0) return code; if (pfont->FontType != ft_CID_bitmap) return_error(gs_error_invalidfont); check_write_type(*op, t_string); if (r_size(op) < 22) return_error(gs_error_rangecheck); str = op->value.bytes; if (long_form || metrics[0] != (wx = (int)metrics[0]) || metrics[1] != 0 || height == 0 || ((wx | width | height | (llx + 128) | (lly + 128)) & ~255) != 0 ) { /* Use the long form. */ int i, n = (long_form ? 10 : 6); str[0] = 0; str[1] = long_form; for (i = 0; i < n; ++i) { int v = (int)metrics[i]; /* no floating point widths yet */ str[2 + 2 * i] = (byte)(v >> 8); str[2 + 2 * i + 1] = (byte)v; } r_set_size(op, 2 + n * 2); } else {