Example #1
0
/*
 * Collect a heap-allocated array of floats.  If the key is missing, set
 * *pparray = 0 and return 0; otherwise set *pparray and return the number
 * of elements.  Note that 0-length arrays are acceptable, so if the value
 * returned is 0, the caller must check whether *pparray == 0.
 */
int
fn_build_float_array(const ref * op, const char *kstr, bool required,
                     bool even, const float **pparray, gs_memory_t *mem)
{
    ref *par;
    int code;

    *pparray = 0;
    if (dict_find_string(op, kstr, &par) <= 0)
        return (required ? gs_note_error(gs_error_rangecheck) : 0);
    if (!r_is_array(par))
        return_error(gs_error_typecheck);
    {
        uint size = r_size(par);
        float *ptr = (float *)
            gs_alloc_byte_array(mem, size, sizeof(float), kstr);

        if (ptr == 0)
            return_error(gs_error_VMerror);
        code = dict_float_array_check_param(mem, op, kstr, size,
                                            ptr, NULL,
                                            0, gs_error_rangecheck);
        if (code < 0 || (even && (code & 1) != 0)) {
            gs_free_object(mem, ptr, kstr);
            return(code < 0 ? code : gs_note_error(gs_error_rangecheck));
        }
        *pparray = ptr;
    }
    return code;
}
Example #2
0
static bool
charstring_is_notdef_proc(const gs_memory_t *mem, const ref *pcstr)
{
    if (r_is_array(pcstr) && r_size(pcstr) == 4) {
        ref elts[4];
        long i;

        for (i = 0; i < 4; ++i)
            array_get(mem, pcstr, i, &elts[i]);
        if (r_has_type(&elts[0], t_name) &&
            r_has_type(&elts[1], t_integer) && elts[1].value.intval == 0 &&
            r_has_type(&elts[2], t_integer) && elts[2].value.intval == 0 &&
            r_has_type(&elts[3], t_name)
            ) {
            ref nref;

            name_enter_string(mem, "pop", &nref);
            if (name_eq(&elts[0], &nref)) {
                name_enter_string(mem, "setcharwidth", &nref);
                if (name_eq(&elts[3], &nref))
                    return true;
            }
        }
    }
    return false;
}
Example #3
0
/* Get the additional information for a CIDFontType 0 or 2 CIDFont. */
int
cid_font_data_param(os_ptr op, gs_font_cid_data *pdata, ref *pGlyphDirectory)
{
    int code;
    ref *pgdir;

    check_type(*op, t_dictionary);
    if ((code = cid_font_system_info_param(&pdata->CIDSystemInfo, op)) < 0 ||
            (code = dict_int_param(op, "CIDCount", 0, max_int, -1,
                                   &pdata->CIDCount)) < 0
       )
        return code;
    /*
     * If the font doesn't have a GlyphDirectory, GDBytes is required.
     * If it does have a GlyphDirectory, GDBytes may still be needed for
     * CIDMap: it's up to the client to check this.
     */
    if (dict_find_string(op, "GlyphDirectory", &pgdir) <= 0) {
        /* Standard CIDFont, require GDBytes. */
        make_null(pGlyphDirectory);
        return dict_int_param(op, "GDBytes", 1, MAX_GDBytes, 0,
                              &pdata->GDBytes);
    }
    if (r_has_type(pgdir, t_dictionary) || r_is_array(pgdir)) {
        /* GlyphDirectory, GDBytes is optional. */
        *pGlyphDirectory = *pgdir;
        code = dict_int_param(op, "GDBytes", 0, MAX_GDBytes, 0,
                              &pdata->GDBytes);
        return code;
    } else {
        return_error(e_typecheck);
    }
}
Example #4
0
/* and return maxlen. */
int
dict_float_array_check_param(const gs_memory_t *mem,
                             const ref * pdict, const char *kstr,
                             uint len, float *fvec, const float *defaultvec,
                             int under_error, int over_error)
{
    ref *pdval;
    uint size;
    int code;

    if (pdict == 0 || dict_find_string(pdict, kstr, &pdval) <= 0) {
        if (defaultvec == NULL)
            return 0;
        memcpy(fvec, defaultvec, len * sizeof(float));

        return len;
    }
    if (!r_is_array(pdval))
        return_error(e_typecheck);
    size = r_size(pdval);
    if (size > len)
        return_error(over_error);
    code = process_float_array(mem, pdval, size, fvec);
    return (code < 0 ? code :
            size == len || under_error >= 0 ? size :
            gs_note_error(under_error));
}
Example #5
0
static int
push_execstack(i_ctx_t *i_ctx_p, os_ptr op1, bool include_marks,
               op_proc_t cont)
{
    uint size;
    /*
     * We can't do this directly, because the interpreter
     * might have cached some state.  To force the interpreter
     * to update the stored state, we push a continuation on
     * the exec stack; the continuation is executed immediately,
     * and does the actual transfer.
     */
    uint depth;

    if (!r_is_array(op1))
        return_op_typecheck(op1);
    /* Check the length before the write access per CET 28-03 */
    size = r_size(op1);
    depth = count_exec_stack(i_ctx_p, include_marks);
    if (depth > size)
        return_error(e_rangecheck);
    check_write(*op1);
    {
        int code = ref_stack_store_check(&e_stack, op1, size, 0);

        if (code < 0)
            return code;
    }
    check_estack(1);
    r_set_size(op1, depth);
    push_op_estack(cont);
    return o_push_estack;
}
Example #6
0
static int
zrunandhide(i_ctx_t *i_ctx_p)
{
    os_ptr op = osp;
    es_ptr ep;

    check_op(2);
    if (!r_is_array(op - 1))
        return_op_typecheck(op);
    if (!r_has_attr(op, a_executable))
        return 0;		/* literal object just gets pushed back */
    check_estack(5);
    ep = esp += 5;
    make_mark_estack(ep - 4, es_other, err_end_runandhide); /* error case */
    make_op_estack(ep - 1,  end_runandhide); /* normal case */
    ref_assign(ep, op);
    /* Store the object we are hiding  and it's current tas.type_attrs */
    /* on the exec stack then change to 'noaccess' */
    make_int(ep - 3, (int)op[-1].tas.type_attrs);
    ref_assign(ep - 2, op - 1);
    r_clear_attrs(ep - 2, a_all);
    /* replace the array with a special kind of mark that has a_read access */
    esfile_check_cache();
    pop(2);
    return o_push_estack;
}
Example #7
0
/* Make a transformed font (common code for makefont/scalefont). */
static int
make_font(i_ctx_t *i_ctx_p, const gs_matrix * pmat)
{
    os_ptr op = osp;
    os_ptr fp = op - 1;
    gs_font *oldfont, *newfont;
    int code;
    ref *pencoding = 0;

    code = font_param(fp, &oldfont);
    if (code < 0)
        return code;
    {
        uint space = ialloc_space(idmemory);

        ialloc_set_space(idmemory, r_space(fp));
        if (dict_find_string(fp, "Encoding", &pencoding) > 0 &&
            !r_is_array(pencoding)
            )
            code = gs_note_error(e_invalidfont);
        else {
                /*
                 * Temporarily substitute the new dictionary
                 * for the old one, in case the Encoding changed.
                 */
            ref olddict;

            olddict = *pfont_dict(oldfont);
            *pfont_dict(oldfont) = *fp;
            code = gs_makefont(ifont_dir, oldfont, pmat, &newfont);
            *pfont_dict(oldfont) = olddict;
        }
        ialloc_set_space(idmemory, space);
    }
    if (code < 0)
        return code;
    /*
     * We have to allow for the possibility that the font's Encoding
     * is different from that of the base font.  Note that the
     * font_data of the new font was simply copied from the old one.
     */
    if (pencoding != 0 &&
        !obj_eq(imemory, pencoding, &pfont_data(newfont)->Encoding)
        ) {
        if (newfont->FontType == ft_composite)
            return_error(e_rangecheck);
        /* We should really do validity checking here.... */
        ref_assign(&pfont_data(newfont)->Encoding, pencoding);
        lookup_gs_simple_font_encoding((gs_font_base *) newfont);
    }
    *fp = *pfont_dict(newfont);
    pop(1);
    return 0;
}
Example #8
0
/* Read an array (or packed array) parameter. */
static int
ref_param_read_array(iparam_list * plist, gs_param_name pkey, iparam_loc * ploc)
{
    int code = ref_param_read(plist, pkey, ploc, -1);

    if (code != 0)
	return code;
    if (!r_is_array(ploc->pvalue))
	return iparam_note_error(*ploc, e_typecheck);
    iparam_check_read(*ploc);
    return 0;
}
Example #9
0
/*
 * Similar to fn_build_float_array() except
 * - numeric parameter is accepted and converted to 1-element array
 * - number of elements is not checked for even/odd
 */
int
fn_build_float_array_forced(const ref * op, const char *kstr, bool required,
                     const float **pparray, gs_memory_t *mem)
{
    ref *par;
    int code;
    uint size;
    float *ptr;

    *pparray = 0;
    if (dict_find_string(op, kstr, &par) <= 0)
        return (required ? gs_note_error(gs_error_rangecheck) : 0);

    if( r_is_array(par) )
        size = r_size(par);
    else if(r_type(par) == t_integer || r_type(par) == t_real)
        size = 1;
    else
        return_error(gs_error_typecheck);
    ptr = (float *)gs_alloc_byte_array(mem, size, sizeof(float), kstr);

    if (ptr == 0)
        return_error(gs_error_VMerror);
    if(r_is_array(par) )
        code = dict_float_array_check_param(mem, op, kstr,
                                            size, ptr, NULL,
                                            0, gs_error_rangecheck);
    else {
        code = dict_float_param(op, kstr, 0., ptr); /* defailt cannot happen */
        if( code == 0 )
            code = 1;
    }

    if (code < 0 ) {
        gs_free_object(mem, ptr, kstr);
        return code;
    }
    *pparray = ptr;
    return code;
}
Example #10
0
/* Collect a Function value. */
static int
build_shading_function(i_ctx_t *i_ctx_p, const ref * op, gs_function_t ** ppfn,
                 int num_inputs, gs_memory_t *mem, const float *shading_domain)
{
    ref *pFunction;
    int code;

    *ppfn = 0;
    if (dict_find_string(op, "Function", &pFunction) <= 0)
        return 0;
    if (r_is_array(pFunction)) {
        uint size = r_size(pFunction);
        gs_function_t **Functions;
        uint i;
        gs_function_AdOt_params_t params;

        check_read(*pFunction);
        if (size == 0)
            return_error(gs_error_rangecheck);
        code = alloc_function_array(size, &Functions, mem);
        if (code < 0)
            return code;
        for (i = 0; i < size; ++i) {
            ref rsubfn;

            array_get(imemory, pFunction, (long)i, &rsubfn);
            code = fn_build_function(i_ctx_p, &rsubfn, &Functions[i], mem,
               shading_domain, num_inputs);
            if (code < 0)
                break;
        }
        params.m = num_inputs;
        params.Domain = 0;
        params.n = size;
        params.Range = 0;
        params.Functions = (const gs_function_t * const *)Functions;
        if (code >= 0)
            code = gs_function_AdOt_init(ppfn, &params, mem);
        if (code < 0)
            gs_function_AdOt_free_params(&params, mem);
    } else {
        code = fn_build_function(i_ctx_p, pFunction, ppfn, mem,
            shading_domain, num_inputs);
        if (code < 0)
            return code;
        if ((*ppfn)->params.m != num_inputs) {
            gs_function_free(*ppfn, true, mem);
            return_error(gs_error_rangecheck);
        }
    }
    return code;
}
Example #11
0
/* Calculate bonding box of a box transformed by a matrix. */
static int
zbbox_transform(i_ctx_t *i_ctx_p)
{
    os_ptr op = osp;
    gs_matrix m;
    float bbox[4];
    gs_point aa, az, za, zz;
    double temp;
    int code;

    if ((code = read_matrix(imemory, op, &m)) < 0)
        return code;

    if (!r_is_array(op - 1))
        return_op_typecheck(op - 1);
    check_read(op[-1]);
    if (r_size(op - 1) != 4)
        return_error(gs_error_rangecheck);
    if ((code = process_float_array(imemory, op - 1, 4, bbox) < 0))
        return code;

    gs_point_transform(bbox[0], bbox[1], &m, &aa);
    gs_point_transform(bbox[0], bbox[3], &m, &az);
    gs_point_transform(bbox[2], bbox[1], &m, &za);
    gs_point_transform(bbox[2], bbox[3], &m, &zz);

    if ( aa.x > az.x)
        temp = aa.x, aa.x = az.x, az.x = temp;
    if ( za.x > zz.x)
        temp = za.x, za.x = zz.x, zz.x = temp;
    if ( za.x < aa.x)
        aa.x = za.x;  /* min */
    if ( az.x > zz.x)
        zz.x = az.x;  /* max */

    if ( aa.y > az.y)
        temp = aa.y, aa.y = az.y, az.y = temp;
    if ( za.y > zz.y)
        temp = za.y, za.y = zz.y, zz.y = temp;
    if ( za.y < aa.y)
        aa.y = za.y;  /* min */
    if ( az.y > zz.y)
        zz.y = az.y;  /* max */

    push(2);
    make_real(op - 3, (float)aa.x);
    make_real(op - 2, (float)aa.y);
    make_real(op - 1, (float)zz.x);
    make_real(op    , (float)zz.y);
    return 0;
}
Example #12
0
/* The stack underflow check is harmless in the off-stack case. */
int
check_proc_failed(const ref * pref)
{
    if (r_is_array(pref)) {
        if (r_has_attr(pref, a_executable))
            return e_invalidaccess;
        else
            return e_typecheck;
    } else {
        if (r_has_type(pref, t__invalid))
            return e_stackunderflow;
        else
            return e_typecheck;
    }
}
Example #13
0
/* <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");
}
Example #14
0
/* Get a FontBBox parameter from a font dictionary. */
int
font_bbox_param(const gs_memory_t *mem, const ref * pfdict, double bbox[4])
{
    ref *pbbox;

    /*
     * Pre-clear the bbox in case it's invalid.  The Red Books say that
     * FontBBox is required, but old Adobe interpreters don't require
     * it, and a few user-written fonts don't supply it, or supply one
     * of the wrong size (!); also, PageMaker 5.0 (an Adobe product!)
     * sometimes emits an absurd bbox for Type 1 fonts converted from
     * TrueType.
     */
    bbox[0] = bbox[1] = bbox[2] = bbox[3] = 0.0;
    if (dict_find_string(pfdict, "FontBBox", &pbbox) > 0) {
	if (!r_is_array(pbbox))
	    return_error(e_typecheck);
	if (r_size(pbbox) == 4) {
	    const ref_packed *pbe = pbbox->value.packed;
	    ref rbe[4];
	    int i;
	    int code;
	    float dx, dy, ratio;
	    const float max_ratio = 12; /* From the bug 687594. */

	    for (i = 0; i < 4; i++) {
		packed_get(mem, pbe, rbe + i);
		pbe = packed_next(pbe);
	    }
	    if ((code = num_params(rbe + 3, 4, bbox)) < 0)
		return code;
 	    /* Require "reasonable" values. */
	    dx = bbox[2] - bbox[0];
	    dy = bbox[3] - bbox[1];
	    if (dx <= 0 || dy <= 0 ||
		(ratio = dy / dx) < 1 / max_ratio || ratio > max_ratio
		)
		bbox[0] = bbox[1] = bbox[2] = bbox[3] = 0.0;
	}
    } else if (gs_currentcpsimode(mem)) {
        return_error(e_invalidfont); /* CPSI requires FontBBox */
    }
    return 0;
}
Example #15
0
/* <function_proc> <array> .scalefunction <function_proc> */
static int
zscalefunction(i_ctx_t *i_ctx_p)
{
    os_ptr op = osp;
    gs_function_t *pfn;
    gs_function_t *psfn;
    gs_range_t *ranges;
    int code;
    uint i;

    check_proc(op[-1]);
    pfn = ref_function(op - 1);
    if (pfn == 0 || !r_is_array(op))
        return_error(gs_error_typecheck);
    if (r_size(op) != 2 * pfn->params.n)
        return_error(gs_error_rangecheck);
    ranges = (gs_range_t *)
        gs_alloc_byte_array(imemory, pfn->params.n, sizeof(gs_range_t),
                            "zscalefunction");
    if (ranges == 0)
        return_error(gs_error_VMerror);
    for (i = 0; i < pfn->params.n; ++i) {
        ref rval[2];
        float val[2];

        if ((code = array_get(op, 2 * i, &rval[0])) < 0 ||
            (code = array_get(op, 2 * i + 1, &rval[1])) < 0 ||
            (code = float_params(rval + 1, 2, val)) < 0)
            return code;
        ranges[i].rmin = val[0];
        ranges[i].rmax = val[1];
    }
    code = gs_function_make_scaled(pfn, &psfn, ranges, imemory);
    gs_free_object(imemory, ranges, "zscalefunction");
    if (code < 0 ||
        (code = make_function_proc(i_ctx_p, op - 1, psfn)) < 0) {
        gs_function_free(psfn, true, imemory);
        return code;
    }
    pop(1);
    return 0;
}
Example #16
0
/*
 * Get the additional parameters for a Type 2 font (or FontType 2 FDArray
 * entry in a CIDFontType 0 font), beyond those common to Type 1 and Type 2
 * fonts.
 */
int
type2_font_params(const_os_ptr op, charstring_font_refs_t *pfr,
		  gs_type1_data *pdata1)
{
    int code;
    float dwx, nwx;
    ref *temp;

    pdata1->interpret = gs_type2_interpret;
    pdata1->lenIV = DEFAULT_LENIV_2;
    pdata1->subroutineNumberBias = subr_bias(pfr->Subrs);
    /* Get information specific to Type 2 fonts. */
    if (dict_find_string(pfr->Private, "GlobalSubrs", &temp) > 0) {
	if (!r_is_array(temp))
	    return_error(e_typecheck);
        pfr->GlobalSubrs = temp;
    }
    pdata1->gsubrNumberBias = subr_bias(pfr->GlobalSubrs);
    if ((code = dict_uint_param(pfr->Private, "gsubrNumberBias",
				0, max_uint, pdata1->gsubrNumberBias,
				&pdata1->gsubrNumberBias)) < 0 ||
	(code = dict_float_param(pfr->Private, "defaultWidthX", 0.0,
				 &dwx)) < 0 ||
	(code = dict_float_param(pfr->Private, "nominalWidthX", 0.0,
				 &nwx)) < 0
	)
	return code;
    pdata1->defaultWidthX = float2fixed(dwx);
    pdata1->nominalWidthX = float2fixed(nwx);
    {
	ref *pirs;

	if (dict_find_string(pfr->Private, "initialRandomSeed", &pirs) <= 0)
	    pdata1->initialRandomSeed = 0;
	else if (!r_has_type(pirs, t_integer))
	    return_error(e_typecheck);
	else
	    pdata1->initialRandomSeed = pirs->value.intval;
    }
    return 0;
}
Example #17
0
/* See idparam.h for specification. */
int
dict_int_array_check_param(const gs_memory_t *mem, const ref * pdict,
   const char *kstr, uint len, int *ivec, int under_error, int over_error)
{
    ref pa, *pdval;
    uint size;
    int i, code;

    if (pdict == 0 || dict_find_string(pdict, kstr, &pdval) <= 0)
        return 0;
    if (!r_is_array(pdval))
        return_error(e_typecheck);
    size = r_size(pdval);
    if (size > len)
        return_error(over_error);
    for (i = 0; i < size; i++) {
        code = array_get(mem, pdval, i, &pa);
        if (code < 0)
            return code;
        /* See dict_int_param above for why we allow reals here. */
        switch (r_type(&pa)) {
            case t_integer:
                if (pa.value.intval != (int)pa.value.intval)
                    return_error(e_rangecheck);
                ivec[i] = (int)pa.value.intval;
                break;
            case t_real:
                if (pa.value.realval < min_int ||
                    pa.value.realval > max_int ||
                    pa.value.realval != (int)pa.value.realval
                    )
                    return_error(e_rangecheck);
                ivec[i] = (int)pa.value.realval;
                break;
            default:
                return_error(e_typecheck);
        }
    }
    return (size == len || under_error >= 0 ? size :
            gs_note_error(under_error));
}
Example #18
0
/* <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;
}
Example #19
0
/* Collect parameters for an Axial or Radial shading. */
static int
build_directional_shading(i_ctx_t *i_ctx_p, const ref * op, float *Coords, int num_Coords,
                          float Domain[2], gs_function_t ** pFunction,
                          bool Extend[2], gs_memory_t *mem)
{
    int code = dict_floats_param(imemory, op, "Coords",
                                 num_Coords, Coords, NULL);
    static const float default_Domain[2] = {0, 1};
    ref *pExtend;

    *pFunction = 0;
    if (code < 0 ||
        (code = dict_floats_param_errorinfo(i_ctx_p, op, "Domain", 2, Domain,
                                  default_Domain)) < 0 ||
        (code = build_shading_function(i_ctx_p, op, pFunction, 1, mem, Domain)) < 0
        )
        return code;
    if (!*pFunction)
        return_error(gs_error_undefined);
    if (dict_find_string(op, "Extend", &pExtend) <= 0)
        Extend[0] = Extend[1] = false;
    else {
        ref E0, E1;

        if (!r_is_array(pExtend))
            return_error(gs_error_typecheck);
        else if (r_size(pExtend) != 2)
            return_error(gs_error_rangecheck);
        else if ((array_get(imemory, pExtend, 0L, &E0),
                  !r_has_type(&E0, t_boolean)) ||
                 (array_get(imemory, pExtend, 1L, &E1),
                  !r_has_type(&E1, t_boolean))
            )
            return_error(gs_error_typecheck);
        Extend[0] = E0.value.boolval, Extend[1] = E1.value.boolval;
    }
    return 0;
}
Example #20
0
/* <array> aload <obj_0> ... <obj_n-1> <array> */
static int
zaload(i_ctx_t *i_ctx_p)
{
    os_ptr op = osp;
    ref aref;
    uint asize;

    ref_assign(&aref, op);
    if (!r_is_array(&aref))
        return_op_typecheck(op);
    check_read(aref);
    asize = r_size(&aref);
    if (asize > ostop - op) {	/* Use the slow, general algorithm. */
        int code = ref_stack_push(&o_stack, asize);
        uint i;
        const ref_packed *packed = aref.value.packed;

        if (code < 0)
            return code;
        for (i = asize; i > 0; i--, packed = packed_next(packed))
            packed_get(imemory, packed, ref_stack_index(&o_stack, i));
        *osp = aref;
        return 0;
    }
    if (r_has_type(&aref, t_array))
        memcpy(op, aref.value.refs, asize * sizeof(ref));
    else {
        uint i;
        const ref_packed *packed = aref.value.packed;
        os_ptr pdest = op;

        for (i = 0; i < asize; i++, pdest++, packed = packed_next(packed))
            packed_get(imemory, packed, pdest);
    }
    push(asize);
    ref_assign(op, &aref);
    return 0;
}
Example #21
0
static int
ref_param_begin_read_collection(gs_param_list * plist, gs_param_name pkey,
				gs_param_dict * pvalue,
				gs_param_collection_type_t coll_type)
{
    iparam_list *const iplist = (iparam_list *) plist;
    iparam_loc loc;
    bool int_keys = coll_type != 0;
    int code = ref_param_read(iplist, pkey, &loc, -1);
    dict_param_list *dlist;

    if (code != 0)
	return code;
    dlist = (dict_param_list *)
	gs_alloc_bytes(plist->memory, size_of(dict_param_list),
		       "ref_param_begin_read_collection");
    if (dlist == 0)
	return_error(e_VMerror);
    if (r_has_type(loc.pvalue, t_dictionary)) {
	code = dict_param_list_read(dlist, loc.pvalue, NULL, false,
				    iplist->ref_memory);
	dlist->int_keys = int_keys;
	if (code >= 0)
	    pvalue->size = dict_length(loc.pvalue);
    } else if (int_keys && r_is_array(loc.pvalue)) {
	code = array_indexed_param_list_read(dlist, loc.pvalue, NULL, false,
					     iplist->ref_memory);
	if (code >= 0)
	    pvalue->size = r_size(loc.pvalue);
    } else
	code = gs_note_error(e_typecheck);
    if (code < 0) {
	gs_free_object(plist->memory, dlist, "ref_param_begin_write_collection");
	return iparam_note_error(loc, code);
    }
    pvalue->list = (gs_param_list *) dlist;
    return 0;
}
Example #22
0
static int
zcond(i_ctx_t *i_ctx_p)
{
    os_ptr op = osp;
    es_ptr ep = esp;

    /* Push the array on the e-stack and call the continuation. */
    if (!r_is_array(op))
        return_op_typecheck(op);
    check_execute(*op);
    if ((r_size(op) & 1) != 0)
        return_error(e_rangecheck);
    if (r_size(op) == 0)
        return zpop(i_ctx_p);
    check_estack(3);
    esp = ep += 3;
    ref_assign(ep - 2, op);	/* the cond body */
    make_op_estack(ep - 1, cond_continue);
    array_get(imemory, op, 0L, ep);
    esfile_check_cache();
    pop(1);
    return o_push_estack;
}
Example #23
0
/* <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;
}
Example #24
0
/* <source> <dict> /JPXDecode <file> */
static int
z_jpx_decode(i_ctx_t * i_ctx_p)
{
    os_ptr op = osp;
    ref *sop = NULL;
    ref *csname = NULL;
    stream_jpxd_state state;

    /* it's our responsibility to call set_defaults() */
    state.memory = imemory->non_gc_memory;
    if (s_jpxd_template.set_defaults)
      (*s_jpxd_template.set_defaults)((stream_state *)&state);
    if (r_has_type(op, t_dictionary)) {
        check_dict_read(*op);
        if ( dict_find_string(op, "Alpha", &sop) > 0) {
            check_type(*sop, t_boolean);
            if (sop->value.boolval)
                state.alpha = true;
        }
        if ( dict_find_string(op, "ColorSpace", &sop) > 0) {
            /* parse the value */
            if (r_is_array(sop)) {
                /* assume it's the first array element */
                csname =  sop->value.refs;
            } else if (r_has_type(sop,t_name)) {
                /* use the name directly */
                csname = sop;
            } else {
                dmprintf(imemory, "warning: JPX ColorSpace value is an unhandled type!\n");
            }
            if (csname != NULL) {
                ref sref;
                /* get a reference to the name's string value */
                name_string_ref(imemory, csname, &sref);
                /* request raw index values if the colorspace is /Indexed */
                if (!ISTRCMP(&sref, "Indexed"))
                    state.colorspace = gs_jpx_cs_indexed;
                /* tell the filter what output we want for other spaces */
                else if (!ISTRCMP(&sref, "DeviceGray"))
                    state.colorspace = gs_jpx_cs_gray;
                else if (!ISTRCMP(&sref, "DeviceRGB"))
                    state.colorspace = gs_jpx_cs_rgb;
                else if (!ISTRCMP(&sref, "DeviceCMYK"))
                    state.colorspace = gs_jpx_cs_cmyk;
                else if (!ISTRCMP(&sref, "ICCBased")) {
                    /* The second array element should be the profile's
                       stream dict */
                    ref *csdict = sop->value.refs + 1;
                    ref *nref;
                    ref altname;
                    if (r_is_array(sop) && (r_size(sop) > 1) &&
                      r_has_type(csdict, t_dictionary)) {
                        check_dict_read(*csdict);
                        /* try to look up the alternate space */
                        if (dict_find_string(csdict, "Alternate", &nref) > 0) {
                          name_string_ref(imemory, csname, &altname);
                          if (!ISTRCMP(&altname, "DeviceGray"))
                            state.colorspace = gs_jpx_cs_gray;
                          else if (!ISTRCMP(&altname, "DeviceRGB"))
                            state.colorspace = gs_jpx_cs_rgb;
                          else if (!ISTRCMP(&altname, "DeviceCMYK"))
                            state.colorspace = gs_jpx_cs_cmyk;
                        }
                        /* else guess based on the number of components */
                        if (state.colorspace == gs_jpx_cs_unset &&
                                dict_find_string(csdict, "N", &nref) > 0) {
                          if_debug1m('w', imemory, "[w] JPX image has an external %"PRIpsint
                                     " channel colorspace\n", nref->value.intval);
                          switch (nref->value.intval) {
                            case 1: state.colorspace = gs_jpx_cs_gray;
                                break;
                            case 3: state.colorspace = gs_jpx_cs_rgb;
                                break;
                            case 4: state.colorspace = gs_jpx_cs_cmyk;
                                break;
                          }
                        }
                    }
                }
            } else {
                if_debug0m('w', imemory, "[w] Couldn't read JPX ColorSpace key!\n");
            }
        }
    }

    /* we pass npop=0, since we've no arguments left to consume */
    /* we pass 0 instead of the usual rspace(sop) which will allocate storage
       for filter state from the same memory pool as the stream it's coding.
       this causes no trouble because we maintain no pointers */
    return filter_read(i_ctx_p, 0, &s_jpxd_template,
                       (stream_state *) & state, 0);
}
Example #25
0
/* of the same length as filters, or null. */
static int
zrsdparams(i_ctx_t *i_ctx_p)
{
    os_ptr op = osp;
    ref *pFilter;
    ref *pDecodeParms;
    int Intent = 0;
    bool AsyncRead;
    ref empty_array, filter1_array, parms1_array;
    uint i;
    int code;

    make_empty_array(&empty_array, a_readonly);
    if (dict_find_string(op, "Filter", &pFilter) > 0) {
        if (!r_is_array(pFilter)) {
            if (!r_has_type(pFilter, t_name))
                return_error(e_typecheck);
            make_array(&filter1_array, a_readonly, 1, pFilter);
            pFilter = &filter1_array;
        }
    } else
        pFilter = &empty_array;
    /* If Filter is undefined, ignore DecodeParms. */
    if (pFilter != &empty_array &&
        dict_find_string(op, "DecodeParms", &pDecodeParms) > 0
        ) {
        if (pFilter == &filter1_array) {
            make_array(&parms1_array, a_readonly, 1, pDecodeParms);
            pDecodeParms = &parms1_array;
        } else if (!r_is_array(pDecodeParms))
            return_error(e_typecheck);
        else if (r_size(pFilter) != r_size(pDecodeParms))
            return_error(e_rangecheck);
    } else
        pDecodeParms = 0;
    for (i = 0; i < r_size(pFilter); ++i) {
        ref f, fname, dp;

        array_get(imemory, pFilter, (long)i, &f);
        if (!r_has_type(&f, t_name))
            return_error(e_typecheck);
        name_string_ref(imemory, &f, &fname);
        if (r_size(&fname) < 6 ||
            memcmp(fname.value.bytes + r_size(&fname) - 6, "Decode", 6)
            )
            return_error(e_rangecheck);
        if (pDecodeParms) {
            array_get(imemory, pDecodeParms, (long)i, &dp);
            if (!(r_has_type(&dp, t_dictionary) || r_has_type(&dp, t_null)))
                return_error(e_typecheck);
        }
    }
    code = dict_int_param(op, "Intent", 0, 3, 0, &Intent);
    if (code < 0 && code != e_rangecheck) /* out-of-range int is ok, use 0 */
        return code;
    if ((code = dict_bool_param(op, "AsyncRead", false, &AsyncRead)) < 0
        )
        return code;
    push(1);
    op[-1] = *pFilter;
    if (pDecodeParms)
        *op = *pDecodeParms;
    else
        make_null(op);
    return 0;
}
Example #26
0
/* Finish building a FunctionType 3 (1-Input Stitching) function. */
int
gs_build_function_3(i_ctx_t *i_ctx_p, const ref *op, const gs_function_params_t * mnDR,
		    int depth, gs_function_t ** ppfn, gs_memory_t *mem)
{
    gs_function_1ItSg_params_t params;
    int code;
    extern bool CPSI_mode;

    *(gs_function_params_t *) & params = *mnDR;
    params.Functions = 0;
    params.Bounds = 0;
    params.Encode = 0;
    {
	ref *pFunctions;
	gs_function_t **ptr;
	int i;

	if ((code = dict_find_string(op, "Functions", &pFunctions)) <= 0)
	    return (code < 0 ? code : gs_note_error(e_rangecheck));
	check_array_only(*pFunctions);
	params.k = r_size(pFunctions);
	code = alloc_function_array(params.k, &ptr, mem);
	if (code < 0)
	    return code;
	params.Functions = (const gs_function_t * const *)ptr;
	for (i = 0; i < params.k; ++i) {
	    ref subfn;

	    array_get(mem, pFunctions, (long)i, &subfn);
	    code = fn_build_sub_function(i_ctx_p, &subfn, &ptr[i], depth, mem, 0, 0);
	    if (code < 0)
		goto fail;
	}
    }
    if ((code = fn_build_float_array(op, "Bounds", true, false, &params.Bounds, mem)) != params.k - 1)
	goto fail;
    if (CPSI_mode) {
	/* Adobe implementation doesn't check the Encode length. */
	/* Extra elements are ignored; missing elements are filled with 0. */
	/* CET 12-14m.ps depends on this bug */
	uint sz, k2 = 2 * params.k;
	ref *encode;
	float *p = (float *)gs_alloc_byte_array(mem, k2, sizeof(float), "Encode");

	params.Encode = p;
	if (p == 0) {
	    code = gs_note_error(e_VMerror);
	    goto fail;
	}
	if (dict_find_string(op, "Encode", &encode) <= 0) {
	    code = gs_note_error(e_undefined);
	    goto fail;
	}
	if (!r_is_array(encode)) {
	    code = gs_note_error(e_typecheck);
	    goto fail;
	}
	sz =  min(k2, r_size(encode));
	code = process_float_array(mem, encode, sz, p);
	if (code < 0)
	    goto fail;
	while (sz < k2)
	    p[sz++] = 0.0;
    } else if ((code = fn_build_float_array(op, "Encode", true, true, &params.Encode, mem)) != 2 * params.k)
	goto fail;
    if (params.Range == 0)
	params.n = params.Functions[0]->params.n;
    code = gs_function_1ItSg_init(ppfn, &params, mem);
    if (code >= 0)
	return 0;
fail:
    gs_function_1ItSg_free_params(&params, mem);
    return (code < 0 ? code : gs_note_error(e_rangecheck));
}
Example #27
0
static int
zeqproc(i_ctx_t *i_ctx_p)
{
    os_ptr op = osp;
    ref2_t stack[MAX_DEPTH + 1];
    ref2_t *top = stack;

    make_array(&stack[0].proc1, 0, 1, op - 1);
    make_array(&stack[0].proc2, 0, 1, op);
    for (;;) {
	long i;

	if (r_size(&top->proc1) == 0) {
	    /* Finished these arrays, go up to next level. */
	    if (top == stack) {
		/* We're done matching: it succeeded. */
		make_true(op - 1);
		pop(1);
		return 0;
	    }
	    --top;
	    continue;
	}
	/* Look at the next elements of the arrays. */
	i = r_size(&top->proc1) - 1;
	array_get(imemory, &top->proc1, i, &top[1].proc1);
	array_get(imemory, &top->proc2, i, &top[1].proc2);
	r_dec_size(&top->proc1, 1);
	++top;
	/*
	 * Amazingly enough, the objects' executable attributes are not
	 * required to match.  This means { x load } will match { /x load },
	 * even though this is clearly wrong.
	 */
#if 0
	if (r_has_attr(&top->proc1, a_executable) !=
	    r_has_attr(&top->proc2, a_executable)
	    )
	    break;
#endif
	if (obj_eq(imemory, &top->proc1, &top->proc2)) {
	    /* Names don't match strings. */
	    if (r_type(&top->proc1) != r_type(&top->proc2) &&
		(r_type(&top->proc1) == t_name ||
		 r_type(&top->proc2) == t_name)
		)
		break;
	    --top;		/* no recursion */
	    continue;
	}
	if (r_is_array(&top->proc1) && r_is_array(&top->proc2) &&
	    r_size(&top->proc1) == r_size(&top->proc2) &&
	    top < stack + (MAX_DEPTH - 1)
	    ) {
	    /* Descend into the arrays. */
	    continue;
	}
	break;
    }
    /* An exit from the loop indicates that matching failed. */
    make_false(op - 1);
    pop(1);
    return 0;
}
Example #28
0
/* Append a user path to the current path. */
static inline int
upath_append_aux(os_ptr oppath, i_ctx_t *i_ctx_p, int *pnargs, bool upath_compat)
{
    upath_state ups = UPS_INITIAL;
    ref opcodes;

    if (r_has_type(oppath, t__invalid))
        return_error(e_stackunderflow);
    if (!r_is_array(oppath))
        return_error(e_typecheck);
    check_read(*oppath);
    gs_newpath(igs);
    /****** ROUND tx AND ty ******/

    if ( r_size(oppath) == 2 &&
         array_get(imemory, oppath, 1, &opcodes) >= 0 &&
         r_has_type(&opcodes, t_string)
        ) {			/* 1st element is operands, 2nd is operators */
        ref operands;
        int code, format;
        int repcount = 1;
        const byte *opp;
        uint ocount, i = 0;

        array_get(imemory, oppath, 0, &operands);
        code = num_array_format(&operands);
        if (code < 0)
            return code;
        format = code;
        check_read(opcodes);
        opp = opcodes.value.bytes;
        ocount = r_size(&opcodes);
        while (ocount--) {
            byte opx = *opp++;

            if (opx > UPATH_REPEAT)
                repcount = opx - UPATH_REPEAT;
            else if (opx > UPATH_MAX_OP)
                return_error(e_rangecheck);
            else {		/* operator */
                const up_data_t data = up_data[opx];

                *pnargs = 0;	/* in case of error */
                if (upath_compat && opx == upath_op_ucache) {
                    /* CPSI does not complain about incorrect ucache
                       placement, even though PLRM3 says it's illegal. */
                    ups = ups > UPS_UCACHE ? ups : data.state_after;
                } else {
                    if (!(ups & data.states_before))
                        return_error(e_typecheck);
                    ups = data.state_after;
                }
                do {
                    os_ptr op = osp;
                    byte opargs = data.num_args;

                    while (opargs--) {
                        push(1);
                        (*pnargs)++; /* in case of error */
                        code = num_array_get(imemory, &operands, format, i++, op);
                        switch (code) {
                            case t_integer:
                                r_set_type_attrs(op, t_integer, 0);
                                break;
                            case t_real:
                                r_set_type_attrs(op, t_real, 0);
                                break;
                            default:
                                return_error(e_typecheck);
                        }
                    }
                    code = (*up_ops[opx])(i_ctx_p);
                    if (code < 0)
                        return code;
                }
                while (--repcount);
                repcount = 1;
            }
        }
    } else {	/* Ordinary executable array. */
        const ref *arp = oppath;
        uint ocount = r_size(oppath);
        long index = 0;
        int argcount = 0;
        op_proc_t oproc;
        int opx, code;

        for (; index < ocount; index++) {
            ref rup;
            ref *defp;
            os_ptr op = osp;
            up_data_t data;

            *pnargs = argcount;
            array_get(imemory, arp, index, &rup);
            switch (r_type(&rup)) {
                case t_integer:
                case t_real:
                    argcount++;
                    push(1);
                    *op = rup;
                    break;
                case t_name:
                    if (!r_has_attr(&rup, a_executable) ||
                        dict_find(systemdict, &rup, &defp) <= 0 ||
                        r_btype(defp) != t_operator)
                        return_error(e_typecheck); /* all errors = typecheck */
                    goto xop;
                case t_operator:
                    defp = &rup;
                  xop:if (!r_has_attr(defp, a_executable))
                        return_error(e_typecheck);
                    oproc = real_opproc(defp);
                    for (opx = 0; opx <= UPATH_MAX_OP; opx++)
                        if (oproc == up_ops[opx])
                            break;
                    if (opx > UPATH_MAX_OP)
                        return_error(e_typecheck);
                    data = up_data[opx];
                    if (argcount != data.num_args)
                        return_error(e_typecheck);
                    if (upath_compat && opx == upath_op_ucache) {
                        /* CPSI does not complain about incorrect ucache
                           placement, even though PLRM3 says it's illegal. */
                        ups = ups > UPS_UCACHE ? ups : data.state_after;
                    } else {
                        if (!(ups & data.states_before))
                            return_error(e_typecheck);
                        ups = data.state_after;
                    }
                    code = (*up_ops[opx])(i_ctx_p);
                    if (code < 0) {
                        if (code == e_nocurrentpoint)
                            return_error(e_rangecheck); /* CET 11-22 */
                        return code;
                    }
                    argcount = 0;
                    break;
                default:
                    return_error(e_typecheck);
            }
        }
        if (argcount) {
            *pnargs = argcount;
            return_error(e_typecheck);	/* leftover args */
        }
    }
    if (ups < UPS_SETBBOX)
        return_error(e_typecheck);	/* no setbbox */
    if (ups == UPS_SETBBOX && upath_compat) {
        /*
         * In CPSI compatibility mode, an empty path with a setbbox also
         * does a moveto (but only if the path is empty).  Since setbbox
         * was the last operator, its operands are still on the o-stack.
         */
        osp += 2;
        return zmoveto(i_ctx_p);
    }
    return 0;
}
Example #29
0
/* <string|name> <font_dict> .buildfont9 <string|name> <font> */
static int
zbuildfont9(i_ctx_t *i_ctx_p)
{
    os_ptr op = osp;
    build_proc_refs build;
    int code = build_proc_name_refs(imemory, &build, NULL, "%Type9BuildGlyph");
    gs_font_cid_data common;
    ref GlyphDirectory, GlyphData, DataSource;
    ref *prfda, cfnstr;
    ref *pCIDFontName, CIDFontName;
    gs_font_type1 **FDArray;
    uint FDArray_size;
    int FDBytes;
    uint CIDMapOffset;
    gs_font_base *pfont;
    gs_font_cid0 *pfcid;
    uint i;

    /*
     * If the CIDFont's data have been loaded into VM, GlyphData will be
     * a string or an array of strings; if they are loaded incrementally
     * from a file, GlyphData will be an integer, and DataSource will be
     * a (reusable) stream.
     */
    if (code < 0 ||
        (code = cid_font_data_param(op, &common, &GlyphDirectory)) < 0 ||
        (code = dict_find_string(op, "FDArray", &prfda)) < 0 ||
        (code = dict_find_string(op, "CIDFontName", &pCIDFontName)) <= 0 ||
        (code = dict_int_param(op, "FDBytes", 0, MAX_FDBytes, -1, &FDBytes)) < 0
        )
        return code;
    /*
     * Since build_gs_simple_font may resize the dictionary and cause
     * pointers to become invalid, save CIDFontName
     */
    CIDFontName = *pCIDFontName;
    if (r_has_type(&GlyphDirectory, t_null)) {
        /* Standard CIDFont, require GlyphData and CIDMapOffset. */
        ref *pGlyphData;

        if ((code = dict_find_string(op, "GlyphData", &pGlyphData)) < 0 ||
            (code = dict_uint_param(op, "CIDMapOffset", 0, max_uint - 1,
                                    max_uint, &CIDMapOffset)) < 0)
            return code;
        GlyphData = *pGlyphData;
        if (r_has_type(&GlyphData, t_integer)) {
            ref *pds;
            stream *ignore_s;

            if ((code = dict_find_string(op, "DataSource", &pds)) < 0)
                return code;
            check_read_file(i_ctx_p, ignore_s, pds);
            DataSource = *pds;
        } else {
            if (!r_has_type(&GlyphData, t_string) && !r_is_array(&GlyphData))
                return_error(e_typecheck);
            make_null(&DataSource);
        }
    } else {
        make_null(&GlyphData);
        make_null(&DataSource);
        CIDMapOffset = 0;
    }
    if (!r_is_array(prfda))
        return_error(e_invalidfont);
    FDArray_size = r_size(prfda);
    if (FDArray_size == 0)
        return_error(e_invalidfont);
    FDArray = ialloc_struct_array(FDArray_size, gs_font_type1 *,
                                  &st_gs_font_type1_ptr_element,
                                  "buildfont9(FDarray)");
    if (FDArray == 0)
        return_error(e_VMerror);
    memset(FDArray, 0, sizeof(gs_font_type1 *) * FDArray_size);
    for (i = 0; i < FDArray_size; ++i) {
        ref rfd;

        array_get(imemory, prfda, (long)i, &rfd);
        code = fd_array_element(i_ctx_p, &FDArray[i], &rfd);
        if (code < 0)
            goto fail;
    }
    code = build_gs_outline_font(i_ctx_p, op, &pfont, ft_CID_encrypted,
                                &st_gs_font_cid0, &build,
                                bf_Encoding_optional | bf_UniqueID_ignored,
                                build_gs_simple_font);
    if (code < 0)
        goto fail;
    if (code == 1) {
        /* The font already has a FID, don't need to build it again.
           Release FDArray and return normally.
           fixme: FDArray fonts are thrown for garbager.
           We're not safe to build them after
           build_gs_simple_font(..., &pfont, ...),
           because a failure in building them would throw
           an underbuilt font with unclear consequences.
         */
        ifree_object(FDArray, "buildfont9(FDarray)");
        return 0;
    }
    pfont->procs.enumerate_glyph = gs_font_cid0_enumerate_glyph;
    pfont->procs.glyph_outline = z9_glyph_outline;
    pfont->procs.glyph_info = z9_glyph_info;
    pfcid = (gs_font_cid0 *)pfont;
    pfcid->cidata.common = common;
    pfcid->cidata.CIDMapOffset = CIDMapOffset;
    pfcid->cidata.FDArray = FDArray;
    pfcid->cidata.FDArray_size = FDArray_size;
    pfcid->cidata.FDBytes = FDBytes;
    pfcid->cidata.glyph_data = z9_glyph_data;
    pfcid->cidata.proc_data = 0;	/* for GC */
    if (pfcid->font_name.size == 0) {
        get_font_name(imemory, &cfnstr, &CIDFontName);
        copy_font_name(&pfcid->font_name, &cfnstr);
    }
    ref_assign(&pfont_data(pfont)->u.cid0.GlyphDirectory, &GlyphDirectory);
    ref_assign(&pfont_data(pfont)->u.cid0.GlyphData, &GlyphData);
    ref_assign(&pfont_data(pfont)->u.cid0.DataSource, &DataSource);
    code = define_gs_font(i_ctx_p, (gs_font *)pfont);
    if (code >= 0)
       code = gs_notify_register(&pfont->notify_list, notify_remove_font_type9, pfont);
    if (code >= 0) {
        for (i = 0; i < FDArray_size; ++i) {
            FDArray[i]->dir = pfont->dir;
            FDArray[i]->data.parent = pfont;
        }
        return code;
    }
 fail:
    ifree_object(FDArray, "buildfont9(FDarray)");
    return code;
}
Example #30
0
/* Extract and check the parameters for a gs_data_image_t. */
int
data_image_params(const gs_memory_t *mem, 
		  const ref *op, gs_data_image_t *pim,
		  image_params *pip, bool require_DataSource,
		  int num_components, int max_bits_per_component,
		  bool has_alpha)
{
    int code;
    int decode_size;
    ref *pds;

    check_type(*op, t_dictionary);
    check_dict_read(*op);
    if ((code = dict_int_param(op, "Width", 0, max_int_in_fixed / 2,
			       -1, &pim->Width)) < 0 ||
	(code = dict_int_param(op, "Height", 0, max_int_in_fixed / 2,
			       -1, &pim->Height)) < 0 ||
	(code = dict_matrix_param(mem, op, "ImageMatrix",
				  &pim->ImageMatrix)) < 0 ||
	(code = dict_bool_param(op, "MultipleDataSources", false,
				&pip->MultipleDataSources)) < 0 ||
	(code = dict_int_param(op, "BitsPerComponent", 1,
			       max_bits_per_component, -1,
			       &pim->BitsPerComponent)) < 0 ||
	(code = decode_size = dict_floats_param(mem, op, "Decode",
						num_components * 2,
						&pim->Decode[0], NULL)) < 0 ||
	(code = dict_bool_param(op, "Interpolate", false,
				&pim->Interpolate)) < 0
	)
	return code;
    pip->pDecode = &pim->Decode[0];
    /* Extract and check the data sources. */
    if ((code = dict_find_string(op, "DataSource", &pds)) <= 0) {
	if (require_DataSource)
	    return (code < 0 ? code : gs_note_error(e_rangecheck));
	return 1;		/* no data source */
    }
    if (pip->MultipleDataSources) {
	ref *ds = pip->DataSource;
        long i, n = num_components + (has_alpha ? 1 : 0);
        if (!r_is_array(pds))
            return_error(e_typecheck);
	if (r_size(pds) != n)
	    return_error(e_rangecheck);
	for (i = 0; i < n; ++i)
	    array_get(mem, pds, i, &ds[i]);
        if (r_type(&ds[0]) == t_string) {
            /* We don't have a problem with the strings of different length
             * but Adobe does and CET tast 12-02.ps reports this as an error.
             */
	    if (has_alpha)
                n--;
            for (i = 1; i < n; ++i) {
                if (r_type(&ds[i]) == t_string && r_size(&ds[i]) != r_size(&ds[0])) {
	            return_error(e_rangecheck);
                }
            }
        }
    } else
	pip->DataSource[0] = *pds;
    return 0;
}