Пример #1
0
/* Fill in a gs_param_key_t from a name or int ref. */
static int
ref_to_key(const ref * pref, gs_param_key_t * key, iparam_list *plist)
{
    if (r_has_type(pref, t_name)) {
	ref nref;

	name_string_ref(plist->memory, pref, &nref);
	key->data = nref.value.const_bytes;
	key->size = r_size(&nref);
	key->persistent = false; /* names may be freed */
    } else if (r_has_type(pref, t_integer)) {
	char istr[sizeof(long) * 8 / 3 + 2];
	int len;
	byte *buf;

	sprintf(istr, "%d", pref->value.intval);
	len = strlen(istr);
	/* GC will take care of freeing this: */
	buf = gs_alloc_string(plist->memory, len, "ref_to_key");
	if (!buf)
	    return_error(e_VMerror);
	key->data = buf;
	key->size = len;
	key->persistent = true;
    } else
	return_error(e_typecheck);
    return 0;
}
Пример #2
0
/*
 * make a new dictionary entry.
 */
static int
pl_dict_build_new_entry(pl_dict_t * pdict, const byte * kdata, uint ksize,
                        void *value, pl_dict_entry_t * link)
{                               /* Make a new entry. */
    byte *kstr;
    gs_memory_t *mem = pdict->memory;
    pl_dict_entry_t *pde;

    pde = gs_alloc_struct(mem, pl_dict_entry_t, &st_pl_dict_entry,
                          "pl_dict_put(entry)");
    kstr = (ksize <= pl_dict_max_short_key ? pde->short_key :
            gs_alloc_string(mem, ksize, "pl_dict_put(key)"));
    if (pde == 0 || kstr == 0) {
        if (kstr && kstr != pde->short_key)
            gs_free_string(mem, kstr, ksize, "pl_dict_put(key)");
        gs_free_object(mem, pde, "pl_dict_put(entry)");
        return -1;
    }
    memcpy(kstr, kdata, ksize);
    pde->key.data = (ksize <= pl_dict_max_short_key ? 0 : kstr);
    pde->key.size = ksize;
    pde->link = link;
    pde->value = value;
    pde->next = pdict->entries;
    pdict->entries = pde;
    pdict->entry_count++;
    return 0;
}
Пример #3
0
static int
charstring_make_notdef(gs_glyph_data_t *pgd, gs_font *font)
{
    gs_font_type1 *const pfont = (gs_font_type1 *)font;
    static const byte char_data[4] = {
        139,			/* 0 */
        139,			/* 0 */
        c1_hsbw,
        cx_endchar
    };
    uint len = max(pfont->data.lenIV, 0) + sizeof(char_data);
    byte *chars = gs_alloc_string(font->memory, len, "charstring_make_notdef");

    if (chars == 0)
        return_error(e_VMerror);
    gs_glyph_data_from_string(pgd, chars, len, font);
    if (pfont->data.lenIV < 0)
        memcpy(chars, char_data, sizeof(char_data));
    else {
        crypt_state state = crypt_charstring_seed;

        memcpy(chars + pfont->data.lenIV, char_data, sizeof(char_data));
        gs_type1_encrypt(chars, chars, len, &state);
    }
    return 0;
}
Пример #4
0
/* Return 0 iff the buffer can't be allocated. */
char *
ref_to_string(const ref * pref, gs_memory_t * mem, client_name_t cname)
{
    uint size = r_size(pref);
    char *str = (char *)gs_alloc_string(mem, size + 1, cname);

    if (str == 0)
	return 0;
    memcpy(str, (const char *)pref->value.bytes, size);
    str[size] = 0;
    return str;
}
Пример #5
0
/* Get FontMatrix and FontName parameters. */
static int
sub_font_params(gs_memory_t *mem, const ref *op, gs_matrix *pmat, gs_matrix *pomat, ref *pfname)
{
    ref *pmatrix, *pfontname, *pfontstyle, *porigfont, *pfontinfo;

    if (dict_find_string(op, "FontMatrix", &pmatrix) <= 0 ||
        read_matrix(mem, pmatrix, pmat) < 0
        )
        return_error(e_invalidfont);
    if (dict_find_string(op, "OrigFont", &porigfont) <= 0)
        porigfont = NULL;
    if (pomat!= NULL) {
        if (porigfont == NULL ||
            dict_find_string(porigfont, "FontMatrix", &pmatrix) <= 0 ||
            read_matrix(mem, pmatrix, pomat) < 0
            )
            memset(pomat, 0, sizeof(*pomat));
    }
    /* Use the FontInfo/OrigFontName key preferrentially (created by MS PSCRIPT driver) */
    if ((dict_find_string((porigfont != NULL ? porigfont : op), "FontInfo", &pfontinfo) > 0) &&
        r_has_type(pfontinfo, t_dictionary) &&
        (dict_find_string(pfontinfo, "OrigFontName", &pfontname) > 0)) {
        if ((dict_find_string(pfontinfo, "OrigFontStyle", &pfontstyle) > 0) &&
                r_size(pfontstyle) > 0) {
            const byte *tmpStr1 = pfontname->value.const_bytes;
            const byte *tmpStr2 = pfontstyle->value.const_bytes;
            int fssize1 = r_size(pfontname), fssize2 = r_size(pfontstyle), fssize = fssize1 + fssize2 + 1;
            byte *sfname = gs_alloc_string(mem, fssize, "sub_font_params");

            if (sfname == NULL)
                return_error(e_VMerror);
            memcpy(sfname, tmpStr1, fssize1);
            sfname[fssize1]=',' ;
            memcpy(sfname + fssize1 + 1, tmpStr2, fssize2);
            make_string(pfname, a_readonly, fssize, sfname);
        } else
            get_font_name(mem, pfname, pfontname);
    } else if (dict_find_string((porigfont != NULL ? porigfont : op), ".Alias", &pfontname) > 0) {
        /* If we emulate the font, we want the requested name rather than a substitute. */
        get_font_name(mem, pfname, pfontname);
    } else if (dict_find_string((porigfont != NULL ? porigfont : op), "FontName", &pfontname) > 0) {
        get_font_name(mem, pfname, pfontname);
    } else
        make_empty_string(pfname, a_readonly);
    return 0;
}
Пример #6
0
/* Prepare to write a string value. */
static int
ref_param_write_string_value(ref * pref, const gs_param_string * pvalue,
			     gs_ref_memory_t *imem)
{
    const byte *pdata = pvalue->data;
    uint n = pvalue->size;

    if (pvalue->persistent)
	make_const_string(pref, a_readonly | avm_foreign, n, pdata);
    else {
	byte *pstr = gs_alloc_string((gs_memory_t *)imem, n,
				     "ref_param_write_string");

	if (pstr == 0)
	    return_error(e_VMerror);
	memcpy(pstr, pdata, n);
	make_string(pref, a_readonly | imemory_space(imem), n, pstr);
    }
    return 0;
}
Пример #7
0
/* Convert a file name to a C string by adding a null terminator. */
int
gs_terminate_file_name(gs_parsed_file_name_t * pfn, gs_memory_t *mem,
		       client_name_t cname)
{
    uint len = pfn->len;
    char *fname;

    if (pfn->iodev == NULL)	/* no device */
	pfn->iodev = iodev_default;
    if (pfn->memory)
	return 0;		/* already copied */
    /* Copy the file name to a C string. */
    fname = (char *)gs_alloc_string(mem, len + 1, cname);
    if (fname == 0)
	return_error(gs_error_VMerror);
    memcpy(fname, pfn->fname, len);
    fname[len] = 0;
    pfn->memory = mem;
    pfn->fname = fname;
    pfn->len = len + 1;		/* null terminator */
    return 0;
}
Пример #8
0
static char *
svg_make_color(gx_device_svg *svg, const gx_drawing_color *pdc)
{
    char *paint = (char *)gs_alloc_string(svg->memory, 8, "svg_make_color");

    if (!paint) {
        gs_throw(gs_error_VMerror, "string allocation failed");
        return NULL;
    }

    if (gx_dc_is_pure(pdc)) {
        gx_color_index color = gx_dc_pure_color(pdc);
        sprintf(paint, "#%06x", (int)(color & 0xffffffL));
    } else if (gx_dc_is_null(pdc)) {
        sprintf(paint, "None");
    } else {
        gs_free_string(svg->memory, (byte *)paint, 8, "svg_make_color");
        gs_throw(gs_error_rangecheck, "unknown color type");
        return NULL;
    }

    return paint;
}
Пример #9
0
/* Get bytes from GlyphData or DataSource. */
static int
cid0_read_bytes(gs_font_cid0 *pfont, ulong base, uint count, byte *buf,
                gs_glyph_data_t *pgd)
{
    const font_data *pfdata = pfont_data(pfont);
    byte *data = buf;
    gs_font *gdfont = 0;	/* pfont if newly allocated, 0 if not */
    int code = 0;

    /* Check for overflow. */
    if (base != (long)base || base > base + count)
        return_error(e_rangecheck);
    if (r_has_type(&pfdata->u.cid0.DataSource, t_null)) {
        /* Get the bytes from GlyphData (a string or array of strings). */
        const ref *pgdata = &pfdata->u.cid0.GlyphData;

        if (r_has_type(pgdata, t_string)) {  /* single string */
            uint size = r_size(pgdata);

            if (base >= size || count > size - base)
                return_error(e_rangecheck);
            data = pgdata->value.bytes + base;
        } else {		/* array of strings */
            /*
             * The algorithm is similar to the one in
             * string_array_access_proc in zfont42.c, but it also has to
             * deal with the case where the requested string crosses array
             * elements.
             */
            ulong skip = base;
            uint copied = 0;
            uint index = 0;
            ref rstr;
            uint size;

            for (;; skip -= size, ++index) {
                int code = array_get(pfont->memory, pgdata, index, &rstr);

                if (code < 0)
                    return code;
                if (!r_has_type(&rstr, t_string))
                    return_error(e_typecheck);
                size = r_size(&rstr);
                if (skip < size)
                    break;
            }
            size -= skip;
            if (count <= size) {
                data = rstr.value.bytes + skip;
            } else {		/* multiple strings needed */
                if (data == 0) {  /* no buffer provided */
                    data = gs_alloc_string(pfont->memory, count,
                                           "cid0_read_bytes");
                    if (data == 0)
                        return_error(e_VMerror);
                    gdfont = (gs_font *)pfont; /* newly allocated */
                }
                memcpy(data, rstr.value.bytes + skip, size);
                copied = size;
                while (copied < count) {
                    int code = array_get(pfont->memory, pgdata, ++index, &rstr);

                    if (code < 0)
                        goto err;
                    if (!r_has_type(&rstr, t_string)) {
                        code = gs_note_error(e_typecheck);
                        goto err;
                    }
                    size = r_size(&rstr);
                    if (size > count - copied)
                        size = count - copied;
                    memcpy(data + copied, rstr.value.bytes, size);
                    copied += size;
                }
            }
        }
    } else {
        /* Get the bytes from DataSource (a stream). */
        stream *s;
        uint nread;
        i_ctx_t *i_ctx_p = get_minst_from_memory(pfont->memory)->i_ctx_p;

        check_read_known_file(i_ctx_p, s, &pfdata->u.cid0.DataSource, return_error);
        if (sseek(s, base) < 0)
            return_error(e_ioerror);
        if (data == 0) {	/* no buffer provided */
            data = gs_alloc_string(pfont->memory, count, "cid0_read_bytes");
            if (data == 0)
                return_error(e_VMerror);
            gdfont = (gs_font *)pfont; /* newly allocated */
        }
        if (sgets(s, data, count, &nread) < 0 || nread != count) {
            code = gs_note_error(e_ioerror);
            goto err;
        }
    }
    gs_glyph_data_from_string(pgd, data, count, gdfont);
    return code;
 err:
    if (data != buf)
        gs_free_string(pfont->memory, data, count, "cid0_read_bytes");
    return code;
}
Пример #10
0
/* Set up the color space information for a bitmap image or pattern. */
int
px_image_color_space(gs_image_t *pim,
  const px_bitmap_params_t *params, const gs_string *palette,
  const gs_state *pgs)
{	

    int depth = params->depth;
    gs_color_space *pbase_pcs = NULL;
    gs_color_space *pcs = NULL;
    bool cie_space = false;
    int code = 0;
    switch ( params->color_space ) {
    case eGray:
	pbase_pcs = gs_cspace_new_DeviceGray(pgs->memory);
        pbase_pcs->cmm_icc_profile_data = pgs->icc_manager->default_gray;
        pbase_pcs->type = &gs_color_space_type_ICC;
        rc_increment(pbase_pcs->cmm_icc_profile_data);
	break;
    case eRGB:
        pbase_pcs = gs_cspace_new_DeviceRGB(pgs->memory);
        pbase_pcs->cmm_icc_profile_data = pgs->icc_manager->default_rgb;
        pbase_pcs->type = &gs_color_space_type_ICC;
        rc_increment(pbase_pcs->cmm_icc_profile_data);
        break;
    case eSRGB:
    case eCRGB:
        if ( pl_cspace_init_SRGB(&pbase_pcs, pgs) < 0 )
            /* should not happen */
            return_error(errorInsufficientMemory);
        cie_space = true;
        pbase_pcs->cmm_icc_profile_data = pgs->icc_manager->default_rgb;
        pbase_pcs->type = &gs_color_space_type_ICC;
        rc_increment(pbase_pcs->cmm_icc_profile_data);
	break;
    default:
	return_error(errorIllegalAttributeValue);
    }
    if (pbase_pcs == NULL)
        return_error(errorInsufficientMemory);

    if ( params->indexed ) { 
        pcs = gs_cspace_alloc(pgs->memory, &gs_color_space_type_Indexed);
        if ( pcs == NULL ) {
            /* free the base space also */
            rc_decrement(pbase_pcs, "px_image_color_space");
            return_error(errorInsufficientMemory);
        }
	pcs->base_space = pbase_pcs;
	pcs->params.indexed.hival = (1 << depth) - 1;
	pcs->params.indexed.lookup.table.size = palette->size;
        {
            uint  n = palette->size;
            byte *p = gs_alloc_string(pgs->memory, n,
                           "px_image_color_space(palette)");
            if ( p == 0 ) {
                rc_decrement(pbase_pcs, "px_image_color_space");
                return_error(errorInsufficientMemory);

            }
            memcpy(p, palette->data, n);
            pcs->params.indexed.lookup.table.data = p;
        }
	pcs->params.indexed.use_proc = 0;
    } else {
        pcs = pbase_pcs;
    }
    gs_image_t_init(pim, pcs);
    pim->ColorSpace = pcs;
    pim->BitsPerComponent = depth;
    if ( params->indexed )
	pim->Decode[1] = (1 << depth) - 1;
    /* NB - this needs investigation */
    if (cie_space && !px_is_currentcolor_pattern(pgs)) {
        code = pl_setSRGBcolor((gs_state *)pgs, 0.0, 0.0, 0.0);
    }
    return code;
}
Пример #11
0
/*
 * Create an Indexed color space.  This is a single-use procedure,
 * broken out only for readability.
 */
static int
pdf_indexed_color_space(gx_device_pdf *pdev, cos_value_t *pvalue,
			const gs_color_space *pcs, cos_array_t *pca)
{
    const gs_indexed_params *pip = &pcs->params.indexed;
    const gs_color_space *base_space = pcs->base_space;
    int num_entries = pip->hival + 1;
    int num_components = gs_color_space_num_components(base_space);
    uint table_size = num_entries * num_components;
    /* Guess at the extra space needed for PS string encoding. */
    uint string_size = 2 + table_size * 4;
    uint string_used;
    byte buf[100];		/* arbitrary */
    stream_AXE_state st;
    stream s, es;
    gs_memory_t *mem = pdev->pdf_memory;
    byte *table;
    byte *palette;
    cos_value_t v;
    int code;

    /* PDF doesn't support Indexed color spaces with more than 256 entries. */
    if (num_entries > 256)
	return_error(gs_error_rangecheck);
    if (pdev->CompatibilityLevel < 1.3) {
	switch (gs_color_space_get_index(pcs)) {
	    case gs_color_space_index_Pattern:
	    case gs_color_space_index_Separation:
	    case gs_color_space_index_Indexed:
	    case gs_color_space_index_DeviceN:
		return_error(gs_error_rangecheck);
	    default: DO_NOTHING; 
	}

    }
    table = gs_alloc_string(mem, string_size, "pdf_color_space(table)");
    palette = gs_alloc_string(mem, table_size, "pdf_color_space(palette)");
    if (table == 0 || palette == 0) {
	gs_free_string(mem, palette, table_size,
		       "pdf_color_space(palette)");
	gs_free_string(mem, table, string_size,
		       "pdf_color_space(table)");
	return_error(gs_error_VMerror);
    }
    s_init(&s, mem);
    swrite_string(&s, table, string_size);
    s_init(&es, mem);
    s_init_state((stream_state *)&st, &s_PSSE_template, NULL);
    s_init_filter(&es, (stream_state *)&st, buf, sizeof(buf), &s);
    sputc(&s, '(');
    if (pcs->params.indexed.use_proc) {
	gs_client_color cmin, cmax;
	byte *pnext = palette;
	int i, j;

	/* Find the legal range for the color components. */
	for (j = 0; j < num_components; ++j)
	    cmin.paint.values[j] = (float)min_long,
		cmax.paint.values[j] = (float)max_long;
	gs_color_space_restrict_color(&cmin, base_space);
	gs_color_space_restrict_color(&cmax, base_space);
	/*
	 * Compute the palette values, with the legal range for each
	 * one mapped to [0 .. 255].
	 */
	for (i = 0; i < num_entries; ++i) {
	    gs_client_color cc;

	    gs_cspace_indexed_lookup(pcs, i, &cc);
	    for (j = 0; j < num_components; ++j) {
		float v = (cc.paint.values[j] - cmin.paint.values[j])
		    * 255 / (cmax.paint.values[j] - cmin.paint.values[j]);

		*pnext++ = (v <= 0 ? 0 : v >= 255 ? 255 : (byte)v);
	    }
	}
    } else
	memcpy(palette, pip->lookup.table.data, table_size);
    if (gs_color_space_get_index(base_space) ==
	gs_color_space_index_DeviceRGB
	) {
	/* Check for an all-gray palette3. */
	int i;

	for (i = table_size; (i -= 3) >= 0; )
	    if (palette[i] != palette[i + 1] ||
		palette[i] != palette[i + 2]
		)
		break;
	if (i < 0) {
	    /* Change the color space to DeviceGray. */
	    for (i = 0; i < num_entries; ++i)
		palette[i] = palette[i * 3];
	    table_size = num_entries;
	    base_space = gs_cspace_new_DeviceGray(mem);
	}
    }
    stream_write(&es, palette, table_size);
    gs_free_string(mem, palette, table_size, "pdf_color_space(palette)");
    sclose(&es);
    sflush(&s);
    string_used = (uint)stell(&s);
    table = gs_resize_string(mem, table, string_size, string_used,
			     "pdf_color_space(table)");
    /*
     * Since the array is always referenced by name as a resource
     * rather than being written as a value, even for in-line images,
     * always use the full name for the color space.
     *
     * We don't have to worry about the range of the base space:
     * in PDF, unlike PostScript, the values from the lookup table are
     * scaled automatically.
     */
    if ((code = pdf_color_space(pdev, pvalue, NULL, base_space,
				&pdf_color_space_names, false)) < 0 ||
	(code = cos_array_add(pca,
			      cos_c_string_value(&v, 
						 pdf_color_space_names.Indexed
						 /*pcsn->Indexed*/))) < 0 ||
	(code = cos_array_add(pca, pvalue)) < 0 ||
	(code = cos_array_add_int(pca, pip->hival)) < 0 ||
	(code = cos_array_add_no_copy(pca,
				      cos_string_value(&v, table,
						       string_used))) < 0
	)
	return code;
    return 0;
}
Пример #12
0
/* 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;
}
Пример #13
0
/*
 * Caller should make sure that this device supports saved_pages:
 * dev_proc(dev, dev_spec_op)(dev, gxdso_supports_saved_pages, NULL, 0) == 1
 *
 * Returns < 0 if error, 1 if erasepage needed, 0 if no action needed.
 */
int
gx_saved_pages_param_process(gx_device_printer *pdev, byte *param, int param_size)
{
    byte *param_scan = param;
    int param_left = param_size;
    byte *token;
    int token_size, code, printed_count, collated_copies = 1;
    int tmp_num;			/* during token scanning loop */
    int erasepage_needed = 0;

    while (pdev->child)
        pdev = (gx_device_printer *)pdev->child;

    while ((token = param_parse_token(param_scan, param_left, &token_size)) != NULL) {

        switch (param_find_key(token, token_size)) {
          case PARAM_BEGIN:
            if (pdev->saved_pages_list == NULL) {
                if ((pdev->saved_pages_list = gx_saved_pages_list_new(pdev)) == NULL)
                    return_error(gs_error_VMerror);

                /* We need to change to clist mode. Always uses clist when saving pages */
                pdev->saved_pages_list->save_banding_type = pdev->space_params.banding_type;
                pdev->space_params.banding_type = BandingAlways;
                if ((code = gdev_prn_reallocate_memory((gx_device *)pdev, &pdev->space_params, pdev->width, pdev->height)) < 0)
                    return code;
                erasepage_needed |= 1;
            }
            break;

          case PARAM_END:
            if (pdev->saved_pages_list != NULL) {
                /* restore to what was set before the "begin" */
                pdev->space_params.banding_type = pdev->saved_pages_list->save_banding_type;
                gx_saved_pages_list_free(pdev->saved_pages_list);
                pdev->saved_pages_list = NULL;
                /* We may need to change from clist mode since we forced clist when saving pages */
                code = gdev_prn_reallocate_memory((gx_device *)pdev, &pdev->space_params, pdev->width, pdev->height);
                if (code < 0)
                    return code;
                erasepage_needed |= 1;       /* make sure next page is erased */
            }
            break;

          case PARAM_FLUSH:
            if (pdev->saved_pages_list != NULL) {
                /* Save the collated copy count so the list we return will have it */
                collated_copies = pdev->saved_pages_list->collated_copies;
                gx_saved_pages_list_free(pdev->saved_pages_list);
            }
            /* Always return with an empty list, even if we weren't saving previously */
            if ((pdev->saved_pages_list = gx_saved_pages_list_new(pdev)) == NULL)
                return_error(gs_error_VMerror);
            /* restore the original count */
            pdev->saved_pages_list->collated_copies = collated_copies;
            break;

          case PARAM_COPIES:			/* copies requires a number next */
            /* make sure that we have a list */
            if (pdev->saved_pages_list == NULL) {
                return_error(gs_error_rangecheck);	/* copies not allowed before a 'begin' */
            }
            /* Move to past 'copies' token */
            param_left -= token - param_scan + token_size;
            param_scan = token + token_size;

            if ((token = param_parse_token(param_scan, param_left, &token_size)) == NULL ||
                 param_find_key(token, token_size) != PARAM_NUMBER) {
                emprintf(pdev->memory, "gx_saved_pages_param_process: copies not followed by number.\n");
                return_error(gs_error_typecheck);
            }
            if (sscanf((const char *)token, "%d", &tmp_num) != 1) {
                emprintf1(pdev->memory, "gx_saved_pages_list_print: Number format error '%s'\n", token);
                code = gs_error_typecheck;
                return code;
            }
            pdev->saved_pages_list->collated_copies = tmp_num;	/* save it for our loop */
            break;

          case PARAM_PRINT:
            /* Move to past 'print' token */
            param_left -= token - param_scan + token_size;
            param_scan = token + token_size;

            code = param_left;			/* in case list is NULL, skip rest of string */
            if (pdev->saved_pages_list != NULL) {
                if ((code = gx_saved_pages_list_print(pdev, pdev->saved_pages_list,
                                                 param_scan, param_left, &printed_count)) < 0)
                    return code;
                erasepage_needed |= 1;       /* make sure next page is erased */
            }
            /* adjust for all of the print parameters */
            token_size += code;
            break;

          /* We are expecting an action keyword, so other keywords and tokens */
          /* are not valid here (mostly the 'print' parameters).              */
          default:
            {
                byte *bad_token = gs_alloc_string(pdev->memory, token_size+1, "saved_pages_param_process");
                byte *param_string = gs_alloc_string(pdev->memory, param_size+1, "saved_pages_param_process");
                if (bad_token != NULL && param_string != NULL) {
                    memcpy(bad_token, token, token_size);
                    bad_token[token_size] = 0;          /* terminate string */
                    memcpy(param_string, param, param_size);
                    param_string[param_size] = 0;          /* terminate string */
                    emprintf2(pdev->memory, "*** Invalid saved-pages token '%s'\n *** in param string '%s'\n",
                              bad_token, param_string);
                    gs_free_string(pdev->memory, bad_token, token_size+1,  "saved_pages_param_process");
                    gs_free_string(pdev->memory, param_string, param_size+1,  "saved_pages_param_process");
                }
            }
        }
        /* Move to next token */
        param_left -= token - param_scan + token_size;
        param_scan = token + token_size;

    }
    return erasepage_needed;
}
Пример #14
0
/*
 * Implement get_params for a sample device CRD.  A useful convention,
 * for devices that can provide more than one CRD, is to have a settable
 * parameter CRDName, which gives the name of the CRD in use.  This sample
 * code provides a constant CRDName: making it settable is left as an
 * exercise to the reader.
 */
int
sample_device_crd_get_params(gx_device *pdev, gs_param_list *plist,
			     const char *crd_param_name)
{
    int ecode = 0;

    if (param_requested(plist, "CRDName") > 0) {
	gs_param_string cns;
	int code;

	cns.data = (const byte *)crd_param_name;
	cns.size = strlen(crd_param_name);
	cns.persistent = true;
	code = param_write_string(plist, "CRDName", &cns);
	if (code < 0)
	    ecode = code;
    }
    if (param_requested(plist, crd_param_name) > 0) {
	gs_cie_render *pcrd;
	int code = gs_cie_render1_build(&pcrd, pdev->memory,
					"sample_device_crd_get_params");
	if (code >= 0) {
	    gs_cie_transform_proc3 tpqr;

	    tpqr = bit_TransformPQR;
	    tpqr.driver_name = pdev->dname;
	    code = gs_cie_render1_initialize(pdev->memory, pcrd, NULL,
			&bit_WhitePoint, NULL /*BlackPoint*/,
			NULL /*MatrixPQR*/, &bit_RangePQR, &tpqr,
			NULL /*MatrixLMN*/, &bit_EncodeLMN, &bit_RangeLMN,
			&bit_MatrixABC, &bit_EncodeABC, NULL /*RangeABC*/,
			&bit_RenderTable);
	    if (code >= 0) {
		code = param_write_cie_render1(plist, crd_param_name, pcrd,
					       pdev->memory);
	    }
	    rc_decrement(pcrd, "sample_device_crd_get_params"); /* release */
	}
	if (code < 0)
	    ecode = code;
    }
    if (param_requested(plist, bit_TransformPQR.proc_name) > 0) {
	/*
	 * We definitely do not recommend the following use of a static
	 * to hold the address: this is a shortcut.
	 */
	gs_cie_transform_proc my_proc = bit_TransformPQR_proc;
	byte *my_addr = gs_alloc_string(pdev->memory, sizeof(my_proc),
					"sd_crd_get_params(proc)");
	int code;

	if (my_addr == 0)
	    code = gs_note_error(gs_error_VMerror);
	else {
	    gs_param_string as;

	    memcpy(my_addr, &my_proc, sizeof(my_proc));
	    as.data = my_addr;
	    as.size = sizeof(my_proc);
	    as.persistent = true;
	    code = param_write_string(plist, bit_TransformPQR.proc_name, &as);
	}
	if (code < 0)
	    ecode = code;
    }
    return ecode;
}
Пример #15
0
/* We separate device allocation and initialization at customer request. */
int
gs_initialize_wordimagedevice(gx_device_memory * new_dev, const gs_matrix * pmat,
                              uint width, uint height, const byte * colors, int colors_size,
                              bool word_oriented, bool page_device, gs_memory_t * mem)
{
    const gx_device_memory *proto_dev;
    int palette_count = colors_size;
    int num_components = 1;
    int pcount;
    int bits_per_pixel;
    float x_pixels_per_unit, y_pixels_per_unit;
    byte palette[256 * 3];
    bool has_color;

    switch (colors_size) {
    case 3 * 2:
        palette_count = 2;
        num_components = 3;
    case 2:
        bits_per_pixel = 1;
        break;
    case 3 * 4:
        palette_count = 4;
        num_components = 3;
    case 4:
        bits_per_pixel = 2;
        break;
    case 3 * 16:
        palette_count = 16;
        num_components = 3;
    case 16:
        bits_per_pixel = 4;
        break;
    case 3 * 256:
        palette_count = 256;
        num_components = 3;
    case 256:
        bits_per_pixel = 8;
        break;
    case -16:
        bits_per_pixel = 16;
        palette_count = 0;
        break;
    case -24:
        bits_per_pixel = 24;
        palette_count = 0;
        break;
    case -32:
        bits_per_pixel = 32;
        palette_count = 0;
        break;
    default:
        return_error(gs_error_rangecheck);
    }
    proto_dev = (word_oriented ?
                 gdev_mem_word_device_for_bits(bits_per_pixel) :
                 gdev_mem_device_for_bits(bits_per_pixel));
    if (proto_dev == 0)		/* no suitable device */
        return_error(gs_error_rangecheck);
    pcount = palette_count * 3;
    /* Check to make sure the palette contains white and black, */
    /* and, if it has any colors, the six primaries. */
    if (bits_per_pixel <= 8) {
        const byte *p;
        byte *q;
        int primary_mask = 0;
        int i;

        has_color = false;
        for (i = 0, p = colors, q = palette;
                i < palette_count; i++, q += 3
            ) {
            int mask = 1;

            switch (num_components) {
            case 1:	/* gray */
                q[0] = q[1] = q[2] = *p++;
                break;
            default /* case 3 */ :		/* RGB */
                q[0] = p[0], q[1] = p[1], q[2] = p[2];
                p += 3;
            }
#define shift_mask(b,n)\
  switch ( b ) { case 0xff: mask <<= n; case 0: break; default: mask = 0; }
            shift_mask(q[0], 4);
            shift_mask(q[1], 2);
            shift_mask(q[2], 1);
#undef shift_mask
            primary_mask |= mask;
            if (q[0] != q[1] || q[0] != q[2])
                has_color = true;
        }
        switch (primary_mask) {
        case 129:		/* just black and white */
            if (has_color)	/* color but no primaries */
                return_error(gs_error_rangecheck);
        case 255:		/* full color */
            break;
        default:
            return_error(gs_error_rangecheck);
        }
    } else
        has_color = true;
    /*
     * The initial transformation matrix must map 1 user unit to
     * 1/72".  Let W and H be the width and height in pixels, and
     * assume the initial matrix is of the form [A 0 0 B X Y].
     * Then the size of the image in user units is (W/|A|,H/|B|),
     * hence the size in inches is ((W/|A|)/72,(H/|B|)/72), so
     * the number of pixels per inch is
     * (W/((W/|A|)/72),H/((H/|B|)/72)), or (|A|*72,|B|*72).
     * Similarly, if the initial matrix is [0 A B 0 X Y] for a 90
     * or 270 degree rotation, the size of the image in user
     * units is (W/|B|,H/|A|), so the pixels per inch are
     * (|B|*72,|A|*72).  We forbid non-orthogonal transformation
     * matrices.
     */
    if (is_fzero2(pmat->xy, pmat->yx))
        x_pixels_per_unit = pmat->xx, y_pixels_per_unit = pmat->yy;
    else if (is_fzero2(pmat->xx, pmat->yy))
        x_pixels_per_unit = pmat->yx, y_pixels_per_unit = pmat->xy;
    else
        return_error(gs_error_undefinedresult);
    /* All checks done, initialize the device. */
    if (bits_per_pixel == 1) {
        /* Determine the polarity from the palette. */
        gs_make_mem_device(new_dev, proto_dev, mem,
                           (page_device ? 1 : -1), 0);
        /* This is somewhat bogus, but does the right thing */
        /* in the only cases we care about. */
        gdev_mem_mono_set_inverted(new_dev,
                                   (palette[0] | palette[1] | palette[2]) != 0);
    } else {
        byte *dev_palette = gs_alloc_string(mem, pcount,
                                            "gs_makeimagedevice(palette)");

        if (dev_palette == 0)
            return_error(gs_error_VMerror);
        gs_make_mem_device(new_dev, proto_dev, mem,
                           (page_device ? 1 : -1), 0);
        new_dev->palette.size = pcount;
        new_dev->palette.data = dev_palette;
        memcpy(dev_palette, palette, pcount);
        if (!has_color) {
            new_dev->color_info.num_components = 1;
            new_dev->color_info.max_color = 0;
            new_dev->color_info.dither_colors = 0;
            new_dev->color_info.gray_index = 0;
        }
    }
    /* Memory defice is always initialised as an internal device but */
    /* this is an external device */
    new_dev->retained = true;
    rc_init(new_dev, new_dev->memory, 1);

    new_dev->initial_matrix = *pmat;
    new_dev->MarginsHWResolution[0] = new_dev->HWResolution[0] =
                                          fabs(x_pixels_per_unit) * 72;
    new_dev->MarginsHWResolution[1] = new_dev->HWResolution[1] =
                                          fabs(y_pixels_per_unit) * 72;
    gx_device_set_width_height((gx_device *) new_dev, width, height);
    /* Set the ImagingBBox so we get a correct clipping region. */
    {
        gs_rect bbox;

        bbox.p.x = 0;
        bbox.p.y = 0;
        bbox.q.x = width;
        bbox.q.y = height;
        gs_bbox_transform_inverse(&bbox, pmat, &bbox);
        new_dev->ImagingBBox[0] = bbox.p.x;
        new_dev->ImagingBBox[1] = bbox.p.y;
        new_dev->ImagingBBox[2] = bbox.q.x;
        new_dev->ImagingBBox[3] = bbox.q.y;
        new_dev->ImagingBBox_set = true;
    }
    /* The bitmap will be allocated when the device is opened. */
    new_dev->is_open = false;
    new_dev->bitmap_memory = mem;
    return 0;
}
Пример #16
0
int
gs_image_next_planes(gs_image_enum * penum,
		     gs_const_string *plane_data /*[num_planes]*/,
		     uint *used /*[num_planes]*/)
{
    const int num_planes = penum->num_planes;
    int i;
    int code = 0;

#ifdef DEBUG
    vd_get_dc('i');
    vd_set_shift(0, 0);
    vd_set_scale(0.01);
    vd_set_origin(0, 0);
    if (gs_debug_c('b')) {
	int pi;

	for (pi = 0; pi < num_planes; ++pi)
	    dprintf6("[b]plane %d source=0x%lx,%u pos=%u data=0x%lx,%u\n",
		     pi, (ulong)penum->planes[pi].source.data,
		     penum->planes[pi].source.size, penum->planes[pi].pos,
		     (ulong)plane_data[pi].data, plane_data[pi].size);
    }
#endif
    for (i = 0; i < num_planes; ++i) {
        used[i] = 0;
	if (penum->wanted[i] && plane_data[i].size != 0) {
	    penum->planes[i].source.size = plane_data[i].size;
	    penum->planes[i].source.data = plane_data[i].data;
	}
    }
    for (;;) {
	/* If wanted can vary, only transfer 1 row at a time. */
	int h = (penum->wanted_varies ? 1 : max_int);

	/* Move partial rows from source[] to row[]. */
	for (i = 0; i < num_planes; ++i) {
	    int pos, size;
	    uint raster;

	    if (!penum->wanted[i])
		continue;	/* skip unwanted planes */
	    pos = penum->planes[i].pos;
	    size = penum->planes[i].source.size;
	    raster = penum->image_planes[i].raster;
	    if (size > 0) {
		if (pos < raster && (pos != 0 || size < raster)) {
		    /* Buffer a partial row. */
		    int copy = min(size, raster - pos);
		    uint old_size = penum->planes[i].row.size;

		    /* Make sure the row buffer is fully allocated. */
		    if (raster > old_size) {
			gs_memory_t *mem = gs_image_row_memory(penum);
			byte *old_data = penum->planes[i].row.data;
			byte *row =
			    (old_data == 0 ?
			     gs_alloc_string(mem, raster,
					     "gs_image_next(row)") :
			     gs_resize_string(mem, old_data, old_size, raster,
					      "gs_image_next(row)"));

			if_debug5('b', "[b]plane %d row (0x%lx,%u) => (0x%lx,%u)\n",
				  i, (ulong)old_data, old_size,
				  (ulong)row, raster);
			if (row == 0) {
			    code = gs_note_error(gs_error_VMerror);
			    free_row_buffers(penum, i, "gs_image_next(row)");
			    break;
			}
			penum->planes[i].row.data = row;
			penum->planes[i].row.size = raster;
		    }
		    memcpy(penum->planes[i].row.data + pos,
			   penum->planes[i].source.data, copy);
		    penum->planes[i].source.data += copy;
		    penum->planes[i].source.size = size -= copy;
		    penum->planes[i].pos = pos += copy;
		    used[i] += copy;
		}
	    }
	    if (h == 0)
		continue;	/* can't transfer any data this cycle */
	    if (pos == raster) {
		/*
		 * This plane will be transferred from the row buffer,
		 * so we can only transfer one row.
		 */
		h = min(h, 1);
		penum->image_planes[i].data = penum->planes[i].row.data;
	    } else if (pos == 0 && size >= raster) {
		/* We can transfer 1 or more planes from the source. */
		h = min(h, size / raster);
		penum->image_planes[i].data = penum->planes[i].source.data;
	    } else
		h = 0;		/* not enough data in this plane */
	}
	if (h == 0 || code != 0)
	    break;
	/* Pass rows to the device. */
	if (penum->dev == 0) {
	    /*
	     * ****** NOTE: THE FOLLOWING IS NOT CORRECT FOR ImageType 3
	     * ****** InterleaveType 2, SINCE MASK HEIGHT AND IMAGE HEIGHT
	     * ****** MAY DIFFER (BY AN INTEGER FACTOR).  ALSO, plane_depths[0]
	     * ****** AND plane_widths[0] ARE NOT UPDATED.
	 */
	    if (penum->y + h < penum->height)
		code = 0;
	    else
		h = penum->height - penum->y, code = 1;
	} else {
	    code = gx_image_plane_data_rows(penum->info, penum->image_planes,
					    h, &h);
	    if_debug2('b', "[b]used %d, code=%d\n", h, code);
	    penum->error = code < 0;
	}
	penum->y += h;
	/* Update positions and sizes. */
	if (h == 0)
	    break;
	for (i = 0; i < num_planes; ++i) {
	    int count;

	    if (!penum->wanted[i])
		continue;
	    count = penum->image_planes[i].raster * h;
	    if (penum->planes[i].pos) {
		/* We transferred the row from the row buffer. */
		penum->planes[i].pos = 0;
	    } else {
		/* We transferred the row(s) from the source. */
		penum->planes[i].source.data += count;
		penum->planes[i].source.size -= count;
		used[i] += count;
	    }
	}
	cache_planes(penum);
	if (code > 0)
	    break;
    }
    /* Return the retained data pointers. */
    for (i = 0; i < num_planes; ++i)
	plane_data[i] = penum->planes[i].source;
    vd_release_dc;
    return code;
}
Пример #17
0
static int
px_gstate_client_copy_for(void *to, void *from, gs_state_copy_reason_t reason)
{
#define pxfrom ((px_gstate_t *)from)
#define pxto ((px_gstate_t *)to)
	px_gstate_rc_adjust(pxfrom, 1, pxfrom->memory);
	px_gstate_rc_adjust(pxto, -1, pxto->memory);
	/*
	 * In the context of the PCL XL code, this routine may be called for
	 * gsave, grestore, or gstate (copying the gstate for makepattern
	 * or Pattern rendering).  See gxstate.h for details of the 'from'
	 * and 'to' arguments for each of these cases.
	 *
	 * We have some structures that belong to the individual gstates for
	 * storage management purposes.  Currently these are:
	 *	dither_matrix, temp_pattern_dict
	 * px_gstate_client_alloc initializes them to an empty state.
	 * For gsave and gstate, the new current gstate or copied gstate
	 * respectively should have the empty structure.  For grestore,
	 * we want to swap the structures, because we will then free the
	 * saved gstate (and release the structure that was in the current
	 * gstate before the grestore).
	 *
	 * halftone.thresholds is a different special case.  We need to
	 * copy it for gsave and gstate, and free it on grestore.
	 */
	{ gs_string tmat;
	  gs_string thtt;
	  pl_dict_t tdict;
	  gs_string *phtt;

	  tmat = pxto->dither_matrix;
	  thtt = pxto->halftone.thresholds;
	  tdict = pxto->temp_pattern_dict;
	  *pxto = *pxfrom;
	  switch ( reason )
	    {
	    case copy_for_gstate:
	      /* Just put back the (empty) 'to' structures. */
	      pxto->dither_matrix = tmat;
	      pxto->temp_pattern_dict = tdict;
	      phtt = &pxto->halftone.thresholds;
	      goto copy;
	    case copy_for_gsave:
	      /* Swap the structures, but set the parent of the new */
	      /* (empty) dictionary to the old one. */
	      pxfrom->dither_matrix = tmat;
	      pxfrom->temp_pattern_dict = tdict;
	      pl_dict_set_parent(&pxfrom->temp_pattern_dict,
				 &pxto->temp_pattern_dict);
	      phtt = &pxfrom->halftone.thresholds;
copy:	      if ( phtt->data )
		{ byte *str = gs_alloc_string(pxfrom->memory, phtt->size,
					      "px_gstate_client_copy(thresholds)");
		  if ( str == 0 )
		    return_error(errorInsufficientMemory);
		  memcpy(str, phtt->data, phtt->size);
		  phtt->data = str;
		}
	      break;
	    default:		/* copy_for_grestore */
	      /* Swap the structures. */
	      pxfrom->dither_matrix = tmat;
	      pxfrom->halftone.thresholds = thtt;
	      pxfrom->temp_pattern_dict = tdict;
	    }
	}
	return 0;
#undef pxfrom
#undef pxto
}