/* width for an xfont character. */ static int op_show_return_width(i_ctx_t *i_ctx_p, uint npop, double *pwidth) { uint index = op_show_find_index(i_ctx_p); es_ptr ep = (es_ptr) ref_stack_index(&e_stack, index - (snumpush - 1)); int code = gs_text_setcharwidth(esenum(ep), pwidth); uint ocount, dsaved, dcount; if (code < 0) return code; /* Restore the operand and dictionary stacks. */ ocount = ref_stack_count(&o_stack) - (uint) esodepth(ep).value.intval; if (ocount < npop) return_error(e_stackunderflow); dsaved = (uint) esddepth(ep).value.intval; dcount = ref_stack_count(&d_stack); if (dcount < dsaved) return_error(e_dictstackunderflow); while (dcount > dsaved) { code = zend(i_ctx_p); if (code < 0) return code; dcount--; } ref_stack_pop(&o_stack, ocount); /* We don't want to pop the mark or the continuation */ /* procedure (op_show_continue or cshow_continue). */ pop_estack(i_ctx_p, index - snumpush); return o_pop_estack; }
/* <obj1> ... <objn> <int> copy <obj1> ... <objn> <obj1> ... <objn> */ static int zcopy_integer(i_ctx_t *i_ctx_p) { os_ptr op = osp; os_ptr op1 = op - 1; int count, i; int code; if ((uint) op->value.intval > (uint)(op - osbot)) { /* There might be enough elements in other blocks. */ check_type(*op, t_integer); if (op->value.intval >= (int)ref_stack_count(&o_stack)) return_error(e_stackunderflow); if (op->value.intval < 0) return_error(e_rangecheck); check_int_ltu(*op, ref_stack_count(&o_stack)); count = op->value.intval; } else if (op1 + (count = op->value.intval) <= ostop) { /* Fast case. */ memcpy((char *)op, (char *)(op - count), count * sizeof(ref)); push(count - 1); return 0; } /* Do it the slow, general way. */ code = ref_stack_push(&o_stack, count - 1); if (code < 0) return code; for (i = 0; i < count; i++) *ref_stack_index(&o_stack, i) = *ref_stack_index(&o_stack, i + count); return 0; }
int ztoken(i_ctx_t *i_ctx_p) { os_ptr op = osp; switch (r_type(op)) { default: return_op_typecheck(op); case t_file: { stream *s; scanner_state state; check_read_file(i_ctx_p, s, op); check_ostack(1); gs_scanner_init(&state, op); return token_continue(i_ctx_p, &state, true); } case t_string: { ref token; /* -1 is to remove the string operand in case of error. */ int orig_ostack_depth = ref_stack_count(&o_stack) - 1; int code; /* Don't pop the operand in case of invalidaccess. */ if (!r_has_attr(op, a_read)) return_error(e_invalidaccess); code = gs_scan_string_token(i_ctx_p, op, &token); switch (code) { case scan_EOF: /* no tokens */ make_false(op); return 0; default: if (code < 0) { /* * Clear anything that may have been left on the ostack, * including the string operand. */ if (orig_ostack_depth < ref_stack_count(&o_stack)) pop(ref_stack_count(&o_stack)- orig_ostack_depth); return code; } } push(2); op[-1] = token; make_true(op); return 0; } } }
/* <key> load <value> */ static int zload(i_ctx_t *i_ctx_p) { os_ptr op = osp; ref *pvalue; switch (r_type(op)) { case t_name: /* Use the fast lookup. */ if ((pvalue = dict_find_name(op)) == 0) return_error(e_undefined); ref_assign(op, pvalue); return 0; case t_null: return_error(e_typecheck); case t__invalid: return_error(e_stackunderflow); default: { /* Use an explicit loop. */ uint size = ref_stack_count(&d_stack); uint i; for (i = 0; i < size; i++) { ref *dp = ref_stack_index(&d_stack, i); check_dict_read(*dp); if (dict_find(dp, op, &pvalue) > 0) { ref_assign(op, pvalue); return 0; } } return_error(e_undefined); } } }
/* * Restore state after finishing, or unwinding from an error within, a show * operation. Note that we assume op == osp, and may reset osp. */ static int op_show_restore(i_ctx_t *i_ctx_p, bool for_error) { register es_ptr ep = esp + snumpush; gs_text_enum_t *penum = esenum(ep); int saved_level = esgslevel(ep).value.intval; int code = 0; if (for_error) { #if 0 /* Disabled for CPSI compatibility for 13-12-4. CPSI doesn't remove cshow, kshow proc operands. */ uint saved_count = esodepth(ep).value.intval; uint count = ref_stack_count(&o_stack); if (count > saved_count) /* if <, we're in trouble */ ref_stack_pop(&o_stack, count - saved_count); #endif if (ep[1].value.opproc == op_show_continue && penum->enum_client_data != NULL) { /* Replace the continuation operaton on estack with the right operator : */ op_proc_t proc; *(void **)&proc = penum->enum_client_data; make_op_estack(ep + 1, proc); } } if (SHOW_IS_STRINGWIDTH(penum) && igs->text_rendering_mode != 3) { /* stringwidth does an extra gsave */ --saved_level; } if (penum->text.operation & TEXT_REPLACE_WIDTHS) { gs_free_const_object(penum->memory, penum->text.y_widths, "y_widths"); if (penum->text.x_widths != penum->text.y_widths) gs_free_const_object(penum->memory, penum->text.x_widths, "x_widths"); } /* * We might have been inside a cshow, in which case currentfont was * reset temporarily, as though we were inside a BuildChar/ BuildGlyph * procedure. To handle this case, set currentfont back to its original * state. NOTE: this code previously used fstack[0] in the enumerator * for the root font: we aren't sure that this change is correct. */ gs_set_currentfont(igs, penum->orig_font); while (igs->level > saved_level && code >= 0) { if (igs->saved == 0 || igs->saved->saved == 0) { /* * Bad news: we got an error inside a save inside a BuildChar or * BuildGlyph. Don't attempt to recover. */ code = gs_note_error(e_Fatal); } else code = gs_grestore(igs); } gs_text_release(penum, "op_show_restore"); return code; }
/* - countdictstack <int> */ static int zcountdictstack(i_ctx_t *i_ctx_p) { os_ptr op = osp; uint count = ref_stack_count(&d_stack); push(1); if (!level2_enabled) count--; /* see dstack.h */ make_int(op, count); return 0; }
/* * Set up to collect the data for the sampled function. This is used for * those alternate tint transforms that cannot be converted into a * type 4 function. */ static int sampled_data_setup(i_ctx_t *i_ctx_p, gs_function_t *pfn, const ref * pproc, int (*finish_proc)(i_ctx_t *), gs_memory_t * mem) { os_ptr op = osp; gs_sampled_data_enum *penum; int i; gs_function_Sd_params_t * params = (gs_function_Sd_params_t *)&pfn->params; check_estack(estack_storage + 1); /* Verify space on estack */ check_ostack(params->m + O_STACK_PAD); /* and the operand stack */ check_ostack(params->n + O_STACK_PAD); /* * Allocate space for the enumerator data structure. */ penum = gs_sampled_data_enum_alloc(imemory, "zbuildsampledfuntion(params)"); if (penum == NULL) return_error(e_VMerror); /* Initialize data in the enumeration structure */ penum->pfn = pfn; for(i=0; i< params->m; i++) penum->indexes[i] = 0; /* * Save stack depth for checking the correct number of values on stack * after the function, which is being sampled, is called. */ penum->o_stack_depth = ref_stack_count(&o_stack); /* * Note: As previously mentioned, we are putting some spare (unused) stack * space under the input values in case the function unbalances the stack. * It is possible for the function to pop or change values on the stack * outside of the input values. (This has been found to happen with some * proc sets from Adobe.) */ push(O_STACK_PAD); for (i = 0; i < O_STACK_PAD; i++) /* Set space = null */ make_null(op - i); /* Push everything on the estack */ esp += estack_storage; make_op_estack(esp - 2, finish_proc); /* Finish proc onto estack */ sample_proc = *pproc; /* Save function to be sampled */ make_istruct(esp, 0, penum); /* Color cube enumeration structure */ push_op_estack(sampled_data_sample); /* Start sampling data */ return o_push_estack; }
/* * Count the number of elements on the exec stack, with or without * the normally invisible elements (*op is a Boolean that indicates this). */ static uint count_exec_stack(i_ctx_t *i_ctx_p, bool include_marks) { uint count = ref_stack_count(&e_stack); if (!include_marks) { uint i; for (i = count; i--;) if (r_has_type_attrs(ref_stack_index(&e_stack, (long)i), t_null, a_executable)) --count; } return count; }
/* <array> dictstack <subarray> */ static int zdictstack(i_ctx_t *i_ctx_p) { os_ptr op = osp; uint count = ref_stack_count(&d_stack); if (!level2_enabled) count--; /* see dstack.h */ if (!r_is_array(op)) return_op_typecheck(op); if (r_size(op) < count) return_error(e_rangecheck); if (!r_has_type_attrs(op, t_array, a_write)) return_error(e_invalidaccess); return ref_stack_store(&d_stack, op, count, 0, 0, true, idmemory, "dictstack"); }
/* Check whether a dictionary is one of the permanent ones on the d-stack. */ bool dstack_dict_is_permanent(const dict_stack_t * pds, const ref * pdref) { dict *pdict = pdref->value.pdict; int i; if (pds->stack.extension_size == 0) { /* Only one block of d-stack. */ for (i = 0; i < pds->min_size; ++i) if (pds->stack.bot[i].value.pdict == pdict) return true; } else { /* More than one block of d-stack. */ uint count = ref_stack_count(&pds->stack); for (i = count - pds->min_size; i < count; ++i) if (ref_stack_index(&pds->stack, i)->value.pdict == pdict) return true; } return false; }
/* <obj_0> ... <obj_n-1> <n> packedarray <packedarray> */ int zpackedarray(i_ctx_t *i_ctx_p) { os_ptr op = osp; int code; ref parr; check_type(*op, t_integer); if (op->value.intval < 0) return_error(e_rangecheck); if (op->value.intval > op - osbot && op->value.intval >= ref_stack_count(&o_stack) ) return_error(e_stackunderflow); osp--; code = make_packed_array(&parr, &o_stack, (uint) op->value.intval, idmemory, "packedarray"); osp++; if (code >= 0) *osp = parr; return code; }
/* <obj_0> ... <obj_n-1> <array> astore <array> */ static int zastore(i_ctx_t *i_ctx_p) { os_ptr op = osp; uint size; int code; if (!r_is_array(op)) return_op_typecheck(op); size = r_size(op); /* Amazingly, the following is valid: 0 array noaccess astore */ if (size == 0) return 0; if (!r_has_type_attrs(op, t_array, a_write)) return_error(gs_error_invalidaccess); if (size > op - osbot) { /* The store operation might involve other stack segments. */ ref arr; if (size >= ref_stack_count(&o_stack)) return_error(gs_error_stackunderflow); arr = *op; code = ref_stack_store(&o_stack, &arr, size, 1, 0, true, idmemory, "astore"); if (code < 0) return code; ref_stack_pop(&o_stack, size); *ref_stack_index(&o_stack, 0) = arr; } else { code = refcpy_to_old(op, 0, op - size, size, idmemory, "astore"); if (code < 0) return code; op[-(int)size] = *op; pop(size); } return 0; }
static int zsethalftone5(i_ctx_t *i_ctx_p) { os_ptr op = osp; uint count; gs_halftone_component *phtc; gs_halftone_component *pc; int code = 0; int j; gs_halftone *pht; gx_device_halftone *pdht; ref sprocs[GS_CLIENT_COLOR_MAX_COMPONENTS + 1]; ref tprocs[GS_CLIENT_COLOR_MAX_COMPONENTS + 1]; gs_memory_t *mem; uint edepth = ref_stack_count(&e_stack); int npop = 2; int dict_enum = dict_first(op); ref rvalue[2]; int cname, colorant_number; byte * pname; uint name_size; int halftonetype, type = 0; gs_state *pgs = igs; int space_index = r_space_index(op - 1); mem = (gs_memory_t *) idmemory->spaces_indexed[space_index]; check_type(*op, t_dictionary); check_dict_read(*op); check_type(op[-1], t_dictionary); check_dict_read(op[-1]); /* * We think that Type 2 and Type 4 halftones, like * screens set by setcolorscreen, adapt automatically to * the device color space, so we need to mark them * with a different internal halftone type. */ dict_int_param(op - 1, "HalftoneType", 1, 5, 0, &type); halftonetype = (type == 2 || type == 4) ? ht_type_multiple_colorscreen : ht_type_multiple; /* Count how many components that we will actually use. */ for (count = 0; ;) { bool have_default = false; /* Move to next element in the dictionary */ if ((dict_enum = dict_next(op, dict_enum, rvalue)) == -1) break; /* * Verify that we have a valid component. We may have a * /HalfToneType entry. */ if (!r_has_type(&rvalue[1], t_dictionary)) continue; /* Get the name of the component verify that we will use it. */ cname = name_index(mem, &rvalue[0]); code = gs_get_colorname_string(mem, cname, &pname, &name_size); if (code < 0) break; colorant_number = gs_cname_to_colorant_number(pgs, pname, name_size, halftonetype); if (colorant_number < 0) continue; else if (colorant_number == GX_DEVICE_COLOR_MAX_COMPONENTS) { /* If here then we have the "Default" component */ if (have_default) return_error(e_rangecheck); have_default = true; } count++; /* * Check to see if we have already reached the legal number of * components. */ if (count > GS_CLIENT_COLOR_MAX_COMPONENTS + 1) { code = gs_note_error(e_rangecheck); break; } } check_estack(5); /* for sampling Type 1 screens */ refset_null(sprocs, count); refset_null(tprocs, count); rc_alloc_struct_0(pht, gs_halftone, &st_halftone, imemory, pht = 0, ".sethalftone5"); phtc = gs_alloc_struct_array(mem, count, gs_halftone_component, &st_ht_component_element, ".sethalftone5"); rc_alloc_struct_0(pdht, gx_device_halftone, &st_device_halftone, imemory, pdht = 0, ".sethalftone5"); if (pht == 0 || phtc == 0 || pdht == 0) { j = 0; /* Quiet the compiler: gs_note_error isn't necessarily identity, so j could be left ununitialized. */ code = gs_note_error(e_VMerror); } else { dict_enum = dict_first(op); for (j = 0, pc = phtc; ;) { int type; /* Move to next element in the dictionary */ if ((dict_enum = dict_next(op, dict_enum, rvalue)) == -1) break; /* * Verify that we have a valid component. We may have a * /HalfToneType entry. */ if (!r_has_type(&rvalue[1], t_dictionary)) continue; /* Get the name of the component */ cname = name_index(mem, &rvalue[0]); code = gs_get_colorname_string(mem, cname, &pname, &name_size); if (code < 0) break; colorant_number = gs_cname_to_colorant_number(pgs, pname, name_size, halftonetype); if (colorant_number < 0) continue; /* Do not use this component */ pc->cname = cname; pc->comp_number = colorant_number; /* Now process the component dictionary */ check_dict_read(rvalue[1]); if (dict_int_param(&rvalue[1], "HalftoneType", 1, 7, 0, &type) < 0) { code = gs_note_error(e_typecheck); break; } switch (type) { default: code = gs_note_error(e_rangecheck); break; case 1: code = dict_spot_params(&rvalue[1], &pc->params.spot, sprocs + j, tprocs + j); pc->params.spot.screen.spot_function = spot1_dummy; pc->type = ht_type_spot; break; case 3: code = dict_threshold_params(&rvalue[1], &pc->params.threshold, tprocs + j); pc->type = ht_type_threshold; break; case 7: code = dict_threshold2_params(&rvalue[1], &pc->params.threshold2, tprocs + j, imemory); pc->type = ht_type_threshold2; break; } if (code < 0) break; pc++; j++; } } if (code >= 0) { pht->type = halftonetype; pht->params.multiple.components = phtc; pht->params.multiple.num_comp = j; pht->params.multiple.get_colorname_string = gs_get_colorname_string; code = gs_sethalftone_prepare(igs, pht, pdht); } if (code >= 0) { /* * Put the actual frequency and angle in the spot function component dictionaries. */ dict_enum = dict_first(op); for (pc = phtc; ; ) { /* Move to next element in the dictionary */ if ((dict_enum = dict_next(op, dict_enum, rvalue)) == -1) break; /* Verify that we have a valid component */ if (!r_has_type(&rvalue[1], t_dictionary)) continue; /* Get the name of the component and verify that we will use it. */ cname = name_index(mem, &rvalue[0]); code = gs_get_colorname_string(mem, cname, &pname, &name_size); if (code < 0) break; colorant_number = gs_cname_to_colorant_number(pgs, pname, name_size, halftonetype); if (colorant_number < 0) continue; if (pc->type == ht_type_spot) { code = dict_spot_results(i_ctx_p, &rvalue[1], &pc->params.spot); if (code < 0) break; } pc++; } } if (code >= 0) { /* * Schedule the sampling of any Type 1 screens, * and any (Type 1 or Type 3) TransferFunctions. * Save the stack depths in case we have to back out. */ uint odepth = ref_stack_count(&o_stack); ref odict, odict5; odict = op[-1]; odict5 = *op; pop(2); op = osp; esp += 5; make_mark_estack(esp - 4, es_other, sethalftone_cleanup); esp[-3] = odict; make_istruct(esp - 2, 0, pht); make_istruct(esp - 1, 0, pdht); make_op_estack(esp, sethalftone_finish); for (j = 0; j < count; j++) { gx_ht_order *porder = NULL; if (pdht->components == 0) porder = &pdht->order; else { /* Find the component in pdht that matches component j in the pht; gs_sethalftone_prepare() may permute these. */ int k; int comp_number = phtc[j].comp_number; for (k = 0; k < count; k++) { if (pdht->components[k].comp_number == comp_number) { porder = &pdht->components[k].corder; break; } } } switch (phtc[j].type) { case ht_type_spot: code = zscreen_enum_init(i_ctx_p, porder, &phtc[j].params.spot.screen, &sprocs[j], 0, 0, space_index); if (code < 0) break; /* falls through */ case ht_type_threshold: if (!r_has_type(tprocs + j, t__invalid)) { /* Schedule TransferFunction sampling. */ /****** check_xstack IS WRONG ******/ check_ostack(zcolor_remap_one_ostack); check_estack(zcolor_remap_one_estack); code = zcolor_remap_one(i_ctx_p, tprocs + j, porder->transfer, igs, zcolor_remap_one_finish); op = osp; } break; default: /* not possible here, but to keep */ /* the compilers happy.... */ ; } if (code < 0) { /* Restore the stack. */ ref_stack_pop_to(&o_stack, odepth); ref_stack_pop_to(&e_stack, edepth); op = osp; op[-1] = odict; *op = odict5; break; } npop = 0; } } if (code < 0) { gs_free_object(mem, pdht, ".sethalftone5"); gs_free_object(mem, phtc, ".sethalftone5"); gs_free_object(mem, pht, ".sethalftone5"); return code; } pop(npop); return (ref_stack_count(&e_stack) > edepth ? o_push_estack : 0); }
/* * Continuation procedure for processing sampled values. */ static int sampled_data_continue(i_ctx_t *i_ctx_p) { os_ptr op = osp; gs_sampled_data_enum *penum = senum; gs_function_Sd_params_t * params = (gs_function_Sd_params_t *)&penum->pfn->params; int i, j, num_out = params->n; int code = 0; byte * data_ptr; double sampled_data_value_max = (double)((1 << params->BitsPerSample) - 1); int bps = bits2bytes(params->BitsPerSample), stack_depth_adjust = 0; /* * Check to make sure that the procedure produced the correct number of * values. If not, move the stack back to where it belongs and abort */ if (num_out + O_STACK_PAD + penum->o_stack_depth != ref_stack_count(&o_stack)) { stack_depth_adjust = ref_stack_count(&o_stack) - penum->o_stack_depth; if (stack_depth_adjust < 0) { /* * If we get to here then there were major problems. The function * removed too many items off of the stack. We had placed extra * (unused) stack stack space to allow for this but the function * exceeded even that. Data on the stack may have been lost. * The only thing that we can do is move the stack pointer back and * hope. (We have not seen real Postscript files that have this * problem.) */ push(-stack_depth_adjust); ifree_object(penum->pfn, "sampled_data_continue(pfn)"); ifree_object(penum, "sampled_data_continue((enum)"); return_error(e_undefinedresult); } } /* Save data from the given function */ data_ptr = cube_ptr_from_index(params, penum->indexes); for (i=0; i < num_out; i++) { ulong cv; double value; double rmin = params->Range[2 * i]; double rmax = params->Range[2 * i + 1]; code = real_param(op + i - num_out + 1, &value); if (code < 0) return code; if (value < rmin) value = rmin; else if (value > rmax) value = rmax; value = (value - rmin) / (rmax - rmin); /* Convert to 0 to 1.0 */ cv = (int) (value * sampled_data_value_max + 0.5); for (j = 0; j < bps; j++) data_ptr[bps * i + j] = (byte)(cv >> ((bps - 1 - j) * 8)); /* MSB first */ } pop(num_out); /* Move op to base of result values */ /* Check if we are done collecting data. */ if (increment_cube_indexes(params, penum->indexes)) { if (stack_depth_adjust == 0) pop(O_STACK_PAD); /* Remove spare stack space */ else pop(stack_depth_adjust - num_out); /* Execute the closing procedure, if given */ code = 0; if (esp_finish_proc != 0) code = esp_finish_proc(i_ctx_p); return code; } else { if (stack_depth_adjust) { stack_depth_adjust -= num_out; push(O_STACK_PAD - stack_depth_adjust); for (i=0;i<O_STACK_PAD - stack_depth_adjust;i++) make_null(op - i); } } /* Now get the data for the next location */ return sampled_data_sample(i_ctx_p); }
/* * 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); } }
static int set_language_level(i_ctx_t *i_ctx_p, int new_level) { int old_level = LANGUAGE_LEVEL; ref *pgdict = /* globaldict, if present */ ref_stack_index(&d_stack, ref_stack_count(&d_stack) - 2); ref *level2dict; int code = 0; if (new_level < 1 || new_level > (dict_find_string(systemdict, "ll3dict", &level2dict) > 0 ? 3 : 2) ) return_error(e_rangecheck); if (dict_find_string(systemdict, "level2dict", &level2dict) <= 0) return_error(e_undefined); /* * As noted in dstack.h, we allocate the extra d-stack entry for * globaldict even in Level 1 mode; in Level 1 mode, this entry * holds an extra copy of systemdict, and [count]dictstack omit the * very bottommost entry. */ while (new_level != old_level) { switch (old_level) { case 1: { /* 1 => 2 or 3 */ /* Put globaldict in the dictionary stack. */ ref *pdict; /* * This might be called so early in initialization that * globaldict hasn't been defined yet. If so, just skip * this step. */ code = dict_find_string(level2dict, "globaldict", &pdict); if (code > 0) { if (!r_has_type(pdict, t_dictionary)) return_error(e_typecheck); *pgdict = *pdict; } /* Set other flags for Level 2 operation. */ imemory->gs_lib_ctx->dict_auto_expand = true; } code = swap_level_dict(i_ctx_p, "level2dict"); if (code < 0) return code; ++old_level; continue; case 3: /* 3 => 1 or 2 */ code = swap_level_dict(i_ctx_p, "ll3dict"); if (code < 0) return code; --old_level; continue; default: /* 2 => 1 or 3 */ break; } switch (new_level) { case 1: { /* 2 => 1 */ /* * Clear the cached definition pointers of all names defined * in globaldict. This will slow down future lookups, but * we don't care. */ int index = dict_first(pgdict); ref elt[2]; while ((index = dict_next(pgdict, index, &elt[0])) >= 0) if (r_has_type(&elt[0], t_name)) name_invalidate_value_cache(imemory, &elt[0]); /* Overwrite globaldict in the dictionary stack. */ *pgdict = *systemdict; /* Set other flags for Level 1 operation. */ imemory->gs_lib_ctx->dict_auto_expand = false; } code = swap_level_dict(i_ctx_p, "level2dict"); break; case 3: /* 2 => 3 */ code = swap_level_dict(i_ctx_p, "ll3dict"); break; default: /* not possible */ return_error(e_Fatal); } break; } dict_set_top(); /* reload dict stack cache */ return code; }
int seticc(i_ctx_t * i_ctx_p, int ncomps, ref *ICCdict, float *range_buff) { os_ptr op = osp; int edepth = ref_stack_count(&e_stack); int code, reuse_op = 0; gs_color_space * pcs; gs_color_space * palt_cs; int i; gs_cie_icc * picc_info; ref * pstrmval; stream * s = 0L; palt_cs = gs_currentcolorspace(igs); /* verify the DataSource entry */ if (dict_find_string(ICCdict, "DataSource", &pstrmval) <= 0) return_error(e_undefined); check_read_file(s, pstrmval); /* build the color space object */ code = gs_cspace_build_CIEICC(&pcs, NULL, gs_state_memory(igs)); if (code < 0) return code; picc_info = pcs->params.icc.picc_info; picc_info->num_components = ncomps; picc_info->instrp = s; picc_info->file_id = (s->read_id | s->write_id); for (i = 0; i < ncomps; i++) { picc_info->Range.ranges[i].rmin = range_buff[2 * i]; picc_info->Range.ranges[i].rmax = range_buff[2 * i + 1]; } /* record the current space as the alternative color space */ pcs->base_space = palt_cs; rc_increment(palt_cs); code = gx_load_icc_profile(picc_info); if (code < 0) return code; /* If the input space to this profile is CIELAB, then we need to adjust the limits */ /* See ICC spec ICC.1:2004-10 Section 6.3.4.2 and 6.4 */ if(picc_info->plu->e_inSpace == icSigLabData) { picc_info->Range.ranges[0].rmin = 0.0; picc_info->Range.ranges[0].rmax = 100.0; picc_info->Range.ranges[1].rmin = -128.0; picc_info->Range.ranges[1].rmax = 127.0; picc_info->Range.ranges[2].rmin = -128.0; picc_info->Range.ranges[2].rmax = 127.0; } /* If the input space is icSigXYZData, then we should do the limits based upon the white point of the profile. */ if(picc_info->plu->e_inSpace == icSigXYZData) { for (i = 0; i < 3; i++) { picc_info->Range.ranges[i].rmin = 0; } picc_info->Range.ranges[0].rmax = picc_info->common.points.WhitePoint.u; picc_info->Range.ranges[1].rmax = picc_info->common.points.WhitePoint.v; picc_info->Range.ranges[2].rmax = picc_info->common.points.WhitePoint.w; } code = cie_cache_joint(i_ctx_p, &istate->colorrendering.procs, (gs_cie_common *)picc_info, igs); if (code < 0) return code; return cie_set_finish( i_ctx_p, pcs, &istate->colorspace.procs.cie, edepth, code ); }
/* This opens %statementedit% or %lineedit% and is also the * continuation proc for callouts. * Input: * string is the statement/line buffer, * int is the write index into string * bool is true if %statementedit% * file is stdin * Output: * file is a string based stream * We store the line being read in a PostScript string. * This limits the size to max_string_size (64k). * This could be increased by storing the input line in something * other than a PostScript string. */ int zfilelineedit(i_ctx_t *i_ctx_p) { uint count = 0; bool in_eol = false; int code; os_ptr op = osp; bool statement; stream *s; stream *ins; gs_string str; uint initial_buf_size; const char *filename; /* * buf exists only for stylistic parallelism: all occurrences of * buf-> could just as well be str. . */ gs_string *const buf = &str; check_type(*op, t_string); /* line assembled so far */ buf->data = op->value.bytes; buf->size = op->tas.rsize; check_type(*(op-1), t_integer); /* index */ count = (op-1)->value.intval; check_type(*(op-2), t_boolean); /* statementedit/lineedit */ statement = (op-2)->value.boolval; check_read_file(ins, op - 3); /* %stdin */ /* extend string */ initial_buf_size = statement ? STATEMENTEDIT_BUF_SIZE : LINEEDIT_BUF_SIZE; if (initial_buf_size > max_string_size) return_error(e_limitcheck); if (!buf->data || (buf->size < initial_buf_size)) { count = 0; buf->data = gs_alloc_string(imemory_system, initial_buf_size, "zfilelineedit(buffer)"); if (buf->data == 0) return_error(e_VMerror); op->value.bytes = buf->data; op->tas.rsize = buf->size = initial_buf_size; } rd: code = zreadline_from(ins, buf, imemory_system, &count, &in_eol); if (buf->size > max_string_size) { /* zreadline_from reallocated the buffer larger than * is valid for a PostScript string. * Return an error, but first realloc the buffer * back to a legal size. */ byte *nbuf = gs_resize_string(imemory_system, buf->data, buf->size, max_string_size, "zfilelineedit(shrink buffer)"); if (nbuf == 0) return_error(e_VMerror); op->value.bytes = buf->data = nbuf; op->tas.rsize = buf->size = max_string_size; return_error(e_limitcheck); } op->value.bytes = buf->data; /* zreadline_from sometimes resizes the buffer. */ op->tas.rsize = buf->size; switch (code) { case EOFC: code = gs_note_error(e_undefinedfilename); /* falls through */ case 0: break; default: code = gs_note_error(e_ioerror); break; case CALLC: { ref rfile; (op-1)->value.intval = count; /* callout is for stdin */ make_file(&rfile, a_readonly | avm_system, ins->read_id, ins); code = s_handle_read_exception(i_ctx_p, code, &rfile, NULL, 0, zfilelineedit); } break; case 1: /* filled buffer */ { uint nsize = buf->size; byte *nbuf; if (nsize >= max_string_size) { code = gs_note_error(e_limitcheck); break; } else if (nsize >= max_string_size / 2) nsize= max_string_size; else nsize = buf->size * 2; nbuf = gs_resize_string(imemory_system, buf->data, buf->size, nsize, "zfilelineedit(grow buffer)"); if (nbuf == 0) { code = gs_note_error(e_VMerror); break; } op->value.bytes = buf->data = nbuf; op->tas.rsize = buf->size = nsize; goto rd; } } if (code != 0) return code; if (statement) { /* If we don't have a complete token, keep going. */ stream st; stream *ts = &st; scanner_state state; ref ignore_value; uint depth = ref_stack_count(&o_stack); int code; /* Add a terminating EOL. */ if (count + 1 > buf->size) { uint nsize; byte *nbuf; nsize = buf->size + 1; if (nsize > max_string_size) { return_error(gs_note_error(e_limitcheck)); } else { nbuf = gs_resize_string(imemory_system, buf->data, buf->size, nsize, "zfilelineedit(grow buffer)"); if (nbuf == 0) { code = gs_note_error(e_VMerror); return_error(code); } op->value.bytes = buf->data = nbuf; op->tas.rsize = buf->size = nsize; } } buf->data[count++] = char_EOL; s_init(ts, NULL); sread_string(ts, buf->data, count); sc: scanner_init_stream_options(&state, ts, SCAN_CHECK_ONLY); code = scan_token(i_ctx_p, &ignore_value, &state); ref_stack_pop_to(&o_stack, depth); if (code < 0) code = scan_EOF; /* stop on scanner error */ switch (code) { case 0: /* read a token */ case scan_BOS: goto sc; /* keep going until we run out of data */ case scan_Refill: goto rd; case scan_EOF: break; default: /* error */ return code; } } buf->data = gs_resize_string(imemory_system, buf->data, buf->size, count, "zfilelineedit(resize buffer)"); if (buf->data == 0) return_error(e_VMerror); op->value.bytes = buf->data; op->tas.rsize = buf->size; s = file_alloc_stream(imemory_system, "zfilelineedit(stream)"); if (s == 0) return_error(e_VMerror); sread_string(s, buf->data, count); s->save_close = s->procs.close; s->procs.close = file_close_disable; filename = statement ? gs_iodev_statementedit.dname : gs_iodev_lineedit.dname; code = ssetfilename(s, (const byte *)filename, strlen(filename)+1); if (code < 0) { sclose(s); return_error(e_VMerror); } pop(3); make_stream_file(osp, s, "r"); return code; }