/* Ws Bs Wd Bd Ps .transformPQR_scale_wb[012] Pd The default TransformPQR procedure is implemented in C, rather than PostScript, as a speed optimization. This TransformPQR implements a relative colorimetric intent by scaling the XYZ values relative to the white and black points. */ static int ztpqr_scale_wb_common(i_ctx_t *i_ctx_p, int idx) { os_ptr op = osp; double a[4], Ps; /* a[0] = ws, a[1] = bs, a[2] = wd, a[3] = bd */ double result; int code; int i; code = real_param(op, &Ps); if (code < 0) return code; for (i = 0; i < 4; i++) { ref tmp; code = array_get(imemory, op - 4 + i, idx, &tmp); if (code >= 0) code = real_param(&tmp, &a[i]); if (code < 0) return code; } if (a[0] == a[1]) return_error(e_undefinedresult); result = a[3] + (a[2] - a[3]) * (Ps - a[1]) / (a[0] - a[1]); make_real(op - 4, result); pop(4); return 0; }
/* <angle> <matrix> rotate <matrix> */ static int zrotate(i_ctx_t *i_ctx_p) { os_ptr op = osp; int code; double ang; if ((code = real_param(op, &ang)) >= 0) { code = gs_rotate(igs, ang); if (code < 0) return code; } else { /* matrix operand */ gs_matrix mat; /* The num_params failure might be a stack underflow. */ check_op(1); if ((code = num_params(op - 1, 1, &ang)) < 0 || (code = gs_make_rotation(ang, &mat)) < 0 || (code = write_matrix(op, &mat)) < 0 ) { /* Might be a stack underflow. */ check_op(2); return code; } op[-1] = *op; } pop(1); return code; }
int float_param(const ref * op, float *pparam) { double dval; int code = real_param(op, &dval); if (code >= 0) *pparam = (float)dval; /* can't overflow */ return code; }
/* <font> <scale> scalefont <new_font> */ static int zscalefont(i_ctx_t *i_ctx_p) { os_ptr op = osp; int code; double scale; gs_matrix mat; if ((code = real_param(op, &scale)) < 0) return code; if ((code = gs_make_scaling(scale, scale, &mat)) < 0) return code; return make_font(i_ctx_p, &mat); }
static int zset_real(i_ctx_t *i_ctx_p, int (*set_proc)(gs_state *, floatp)) { os_ptr op = osp; double param; int code = real_param(op, ¶m); if (code < 0) return_op_typecheck(op); code = set_proc(igs, param); if (!code) pop(1); return code; }
/* <alpha> setalpha - */ static int zsetalpha(i_ctx_t *i_ctx_p) { os_ptr op = osp; double alpha; int code; if (real_param(op, &alpha) < 0) return_op_typecheck(op); if ((code = gs_setalpha(igs, alpha)) < 0) return code; pop(1); return 0; }
/* <smoothness> setsmoothness - */ static int zsetsmoothness(i_ctx_t *i_ctx_p) { os_ptr op = osp; double smoothness; int code; if (real_param(op, &smoothness) < 0) return_op_typecheck(op); if ((code = gs_setsmoothness(igs, smoothness)) < 0) return code; pop(1); return 0; }
/* Continuation procedure for processing sampled pixels. */ static int set_screen_continue(i_ctx_t *i_ctx_p) { os_ptr op = osp; double value; int code = real_param(op, &value); if (code < 0) return code; code = gs_screen_next(senum, value); if (code < 0) return code; pop(1); return screen_sample(i_ctx_p); }
/* <num> <bool> .setdotlength - */ static int zsetdotlength(i_ctx_t *i_ctx_p) { os_ptr op = osp; double length; int code = real_param(op - 1, &length); if (code < 0) return code; check_type(*op, t_boolean); code = gs_setdotlength(igs, length, op->value.boolval); if (code < 0) return code; pop(2); return 0; }
/* dissolve - */ static int zdissolve(i_ctx_t *i_ctx_p) { os_ptr op = osp; gs_composite_alpha_params_t params; double delta; int code = real_param(op, &delta); if (code < 0) return code; if (delta < 0 || delta > 1) return_error(e_rangecheck); params.op = composite_Dissolve; params.delta = delta; return composite_image(i_ctx_p, ¶ms); }
/* <num> setlinewidth - */ static int zsetlinewidth(i_ctx_t *i_ctx_p) { os_ptr op = osp; /* * The Red Book doesn't say anything about this, but Adobe * interpreters return (or perhaps store) the absolute value * of the width. */ double width; int code = real_param(op, &width); if (code < 0) return_op_typecheck(op); code = gs_setlinewidth(igs, fabs(width)); if (code >= 0) pop(1); return code; }
/* <array> <offset> setdash - */ static int zsetdash(i_ctx_t *i_ctx_p) { os_ptr op = osp; os_ptr op1 = op - 1; double offset; int code = real_param(op, &offset); uint i, n; gs_memory_t *mem = imemory; float *pattern; if (code < 0) return_op_typecheck(op); if (!r_is_array(op1)) return_op_typecheck(op1); /* Adobe interpreters apparently don't check the array for */ /* read access, so we won't either. */ /*check_read(*op1); */ /* Unpack the dash pattern and check it */ n = r_size(op1); pattern = (float *)gs_alloc_byte_array(mem, n, sizeof(float), "setdash"); if (pattern == 0) return_error(e_VMerror); for (i = 0, code = 0; i < n && code >= 0; ++i) { ref element; array_get(mem, op1, (long)i, &element); code = float_param(&element, &pattern[i]); } if (code >= 0) code = gs_setdash(igs, pattern, n, offset); gs_free_object(mem, pattern, "setdash"); /* gs_setdash copies this */ if (code < 0) return code; ref_assign(&istate->dash_pattern_array, op1); pop(2); return code; }
/* <mark> <x0> <y0> ... <xn> <yn> .pdfinkpath - */ static int zpdfinkpath(i_ctx_t *i_ctx_p) { os_ptr optr, op = osp; uint count = ref_stack_counttomark(&o_stack); uint i, ocount; int code; double x0, y0, x1, y1, x2, y2, x3, y3, xc1, yc1, xc2, yc2, xc3, yc3; double len1, len2, len3, k1, k2, xm1, ym1, xm2, ym2; double ctrl1_x, ctrl1_y, ctrl2_x, ctrl2_y; const double smooth_value = 1; /* from 0..1 range */ if (count == 0) return_error(e_unmatchedmark); if ((count & 1) == 0 || count < 3) return_error(e_rangecheck); ocount = count - 1; optr = op - ocount + 1; if ((code = real_param(optr, &x1)) < 0) return code; if ((code = real_param(optr + 1, &y1)) < 0) return code; if ((code = gs_moveto(igs, x1, y1)) < 0) return code; if (ocount == 2) goto pop; if ((code = real_param(optr + 2, &x2)) < 0) return code; if ((code = real_param(optr + 3, &y2)) < 0) return code; if (ocount == 4) { if((code = gs_lineto(igs, x2, y2)) < 0) return code; goto pop; } x0 = 2*x1 - x2; y0 = 2*y1 - y2; for (i = 4; i <= ocount; i += 2) { if (i < ocount) { if ((code = real_param(optr + i, &x3)) < 0) return code; if ((code = real_param(optr + i + 1, &y3)) < 0) return code; } else { x3 = 2*x2 - x1; y3 = 2*y2 - y1; } xc1 = (x0 + x1) / 2.0; yc1 = (y0 + y1) / 2.0; xc2 = (x1 + x2) / 2.0; yc2 = (y1 + y2) / 2.0; xc3 = (x2 + x3) / 2.0; yc3 = (y2 + y3) / 2.0; len1 = hypot(x1 - x0, y1 - y0); len2 = hypot(x2 - x1, y2 - y1); len3 = hypot(x3 - x2, y3 - y2); k1 = len1 / (len1 + len2); k2 = len2 / (len2 + len3); xm1 = xc1 + (xc2 - xc1) * k1; ym1 = yc1 + (yc2 - yc1) * k1; xm2 = xc2 + (xc3 - xc2) * k2; ym2 = yc2 + (yc3 - yc2) * k2; ctrl1_x = xm1 + (xc2 - xm1) * smooth_value + x1 - xm1; ctrl1_y = ym1 + (yc2 - ym1) * smooth_value + y1 - ym1; ctrl2_x = xm2 + (xc2 - xm2) * smooth_value + x2 - xm2; ctrl2_y = ym2 + (yc2 - ym2) * smooth_value + y2 - ym2; code = gs_curveto(igs, ctrl1_x, ctrl1_y, ctrl2_x, ctrl2_y, x2, y2); if (code < 0) return code; x0 = x1, x1 = x2, x2 = x3; y0 = y1, y1 = y2, y2 = y3; } pop: ref_stack_pop(&o_stack, count); return 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); }