Example #1
0
/* Close the device */
static int
svg_close_device(gx_device *dev)
{
    gx_device_svg *const svg = (gx_device_svg*)dev;

    svg_write(svg, "\n<!-- svg_close_device -->\n");
    /* close any open group elements */
    while (svg->mark > 0) {
        svg_write(svg, "</g>\n");
        svg->mark--;
    }
    if (svg->header) {
        svg_write(svg, "</svg>\n");
        svg->header = 0;
    }

    if (svg->fillcolor) gs_free_string(svg->memory,
                                           (byte *)svg->fillcolor, 8, "svg_close_device");
    if (svg->strokecolor) gs_free_string(svg->memory,
                                             (byte *)svg->strokecolor, 8, "svg_close_device");

    if (ferror(svg->file))
        return gs_throw_code(gs_error_ioerror);

    return gdev_vector_close_file((gx_device_vector*)dev);
}
Example #2
0
static int
svg_setstrokecolor(gx_device_vector *vdev, const gs_imager_state *pis,
                   const gx_drawing_color *pdc)
{
    gx_device_svg *svg = (gx_device_svg*)vdev;
    char *stroke;

    dprintf("svg_setstrokecolor\n");

    stroke = svg_make_color(svg, pdc);
    if (!stroke)
        return gs_rethrow_code(gs_error_VMerror);
    if (svg->strokecolor && !strcmp(stroke, svg->strokecolor))
        return 0; /* not a new color */

    /* update our state with the new color */
    if (svg->strokecolor)
        gs_free_string(svg->memory, (byte *)svg->strokecolor, 8,
                       "svg_setstrokecolor");
    svg->strokecolor = stroke;
    /* request a new group element */
    svg->dirty++;

    return 0;
}
Example #3
0
int pdf_font_descriptor_free(gx_device_pdf *pdev, pdf_resource_t *pres)
{
    pdf_font_descriptor_t *pfd = (pdf_font_descriptor_t *)pres;
    pdf_base_font_t *pbfont = pfd->base_font;
    gs_font *copied = (gs_font *)pbfont->copied, *complete = (gs_font *)pbfont->complete;

    gs_free_copied_font(copied);
    if (complete && copied != complete) {
        gs_free_copied_font(complete);
        pbfont->complete = 0;
    }
    pbfont->copied = 0;
    if (pbfont && pbfont->font_name.size) {
        gs_free_string(pdev->pdf_memory, pbfont->font_name.data, pbfont->font_name.size, "Free BaseFont FontName string");
        pbfont->font_name.data = (byte *)0L;
        pbfont->font_name.size = 0;
    }
    if (pbfont) {
        gs_free_object(cos_object_memory(pres->object), pbfont, "Free base font from FontDescriptor)");
        pfd->base_font = 0;
    }
    if (pres->object) {
        gs_free_object(cos_object_memory(pres->object), pres->object, "free FontDescriptor object");
        pres->object = NULL;
    }
    return 0;
}
Example #4
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;
}
Example #5
0
static void
px_gstate_client_free(void *old, gs_memory_t *mem)
{	px_gstate_t *pxgs = old;

	px_dict_release(&pxgs->temp_pattern_dict);
	if ( pxgs->halftone.thresholds.data )
            gs_free_string(mem, (byte *)pxgs->halftone.thresholds.data,
			 pxgs->halftone.thresholds.size,
			 "px_gstate_free(halftone.thresholds)");
	if ( pxgs->dither_matrix.data )
            gs_free_string(mem, (byte *)pxgs->dither_matrix.data,
			 pxgs->dither_matrix.size,
			 "px_gstate_free(dither_matrix)");
	px_gstate_rc_adjust(old, -1, mem);
	gs_free_object(mem, old, "px_gstate_free");
}
Example #6
0
/* Delete a dictionary entry. */
static void
pl_dict_free(pl_dict_t * pdict, pl_dict_entry_t ** ppde, client_name_t cname)
{
    pl_dict_entry_t *pde = *ppde;
    gs_memory_t *mem = pdict->memory;

    *ppde = pde->next;
    if (!pde->link)             /* values are not freed for links */
        (*pdict->free_proc) (mem, pde->value, cname);
    if (pde->key.size > pl_dict_max_short_key)
        gs_free_string(mem, (byte *) pde->key.data, pde->key.size, cname);
    gs_free_object(mem, pde, cname);
    pdict->entry_count--;
}
Example #7
0
/* Free the row buffers when cleaning up. */
static void
free_row_buffers(gs_image_enum *penum, int num_planes, client_name_t cname)
{
    int i;

    for (i = num_planes - 1; i >= 0; --i) {
	if_debug3('b', "[b]free plane %d row (0x%lx,%u)\n",
		  i, (ulong)penum->planes[i].row.data,
		  penum->planes[i].row.size);
	gs_free_string(gs_image_row_memory(penum), penum->planes[i].row.data,
		       penum->planes[i].row.size, cname);
	penum->planes[i].row.data = 0;
	penum->planes[i].row.size = 0;
    }
}
Example #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;
}
Example #9
0
int
pxPopGS(px_args_t *par, px_state_t *pxs)
{	gs_state *pgs = pxs->pgs;
	px_gstate_t *pxgs = pxs->pxgs;
	int code;

	/*
	 * Even though the H-P documentation says that a PopGS with an
	 * empty stack is illegal, the implementations apparently simply
	 * do nothing in this case.
	 */
	if ( pxgs->stack_depth == 0 )
	  return 0;
	if ( pxgs->palette.data && !pxgs->palette_is_shared ) {
            gs_free_string(pxs->memory, (byte *)pxgs->palette.data,
			 pxgs->palette.size, "pxPopGS(palette)");
	  pxgs->palette.data = 0;
	}
	px_purge_pattern_cache(pxs, eTempPattern);
	code = gs_grestore(pgs);
	pxs->pxgs = gs_state_client_data(pgs);
	return code;
}
Example #10
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;
}
Example #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;
}
Example #12
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;
}