예제 #1
0
파일: gdevdrop.c 프로젝트: 99years/plan9
/*
 * The default implementation for non-memory devices uses get_bits_rectangle
 * to read out the pixels, the memory device implementation to do the
 * operation, and copy_color to write the pixels back.
 */
int
gx_default_strip_copy_rop(gx_device * dev,
			  const byte * sdata, int sourcex,
			  uint sraster, gx_bitmap_id id,
			  const gx_color_index * scolors,
			  const gx_strip_bitmap * textures,
			  const gx_color_index * tcolors,
			  int x, int y, int width, int height,
			  int phase_x, int phase_y,
			  gs_logical_operation_t lop)
{
    int depth = dev->color_info.depth;
    gs_memory_t *mem = dev->memory;
    const gx_device_memory *mdproto = gdev_mem_device_for_bits(depth);
    gx_device_memory mdev;
    uint draster;
    byte *row = 0;
    gs_int_rect rect;
    int max_height;
    int block_height;
    int code;
    int py;

#ifdef DEBUG
    if (gs_debug_c('b'))
	trace_copy_rop("gx_default_strip_copy_rop",
		       dev, sdata, sourcex, sraster,
		       id, scolors, textures, tcolors,
		       x, y, width, height, phase_x, phase_y, lop);
#endif
    if (mdproto == 0)
	return_error(gs_error_rangecheck);
    if (sdata == 0) {
	fit_fill(dev, x, y, width, height);
    } else {
	fit_copy(dev, sdata, sourcex, sraster, id, x, y, width, height);
    }
    draster = bitmap_raster(width * depth);
    max_height = max_rop_bitmap / draster;
    if (max_height == 0)
	max_height = 1;
    block_height = min(height, max_height);
    gs_make_mem_device(&mdev, mdproto, mem, -1, dev);
    gx_device_retain((gx_device *)&mdev, true);	/* prevent freeing */
    mdev.width = width;
    mdev.height = block_height;
    mdev.bitmap_memory = mem;
    mdev.color_info = dev->color_info;
    code = (*dev_proc(&mdev, open_device))((gx_device *)&mdev);
    if (code < 0)
	return code;
    if (rop3_uses_D(gs_transparent_rop(lop))) {
	row = gs_alloc_bytes(mem, draster * block_height, "copy_rop row");
	if (row == 0) {
	    code = gs_note_error(gs_error_VMerror);
	    goto out;
	}
    }
    rect.p.x = x;
    rect.q.x = x + width;
    for (py = y; py < y + height; py += block_height) {
	if (block_height > y + height - py)
	    block_height = y + height - py;
	rect.p.y = py;
	rect.q.y = py + block_height;
	if (row /*uses_d*/) {
	    gs_get_bits_params_t bit_params;

	    bit_params.options =
		GB_COLORS_NATIVE | GB_ALPHA_NONE | GB_DEPTH_ALL |
		GB_PACKING_CHUNKY | GB_RETURN_ALL | GB_ALIGN_STANDARD |
		GB_OFFSET_0 | GB_OFFSET_ANY | GB_RASTER_STANDARD;
	    bit_params.data[0] = row;
	    bit_params.x_offset = 0;
	    code = (*dev_proc(dev, get_bits_rectangle))
		(dev, &rect, &bit_params, NULL);
	    if (code < 0)
		break;
	    code = (*dev_proc(&mdev, copy_color))
		((gx_device *)&mdev, bit_params.data[0], bit_params.x_offset,
		 draster, gx_no_bitmap_id, 0, 0, width,
		 block_height);
	    if (code < 0)
		return code;
	}
	code = (*dev_proc(&mdev, strip_copy_rop))
	    ((gx_device *)&mdev,
	     sdata + (py - y) * sraster, sourcex, sraster,
	     gx_no_bitmap_id, scolors, textures, tcolors,
	     0, 0, width, block_height, phase_x + x, phase_y + py, lop);
	if (code < 0)
	    break;
	code = (*dev_proc(dev, copy_color))
	    (dev, scan_line_base(&mdev, 0), 0, draster, gx_no_bitmap_id,
	     x, py, width, block_height);
	if (code < 0)
	    break;
    }
out:
    gs_free_object(mem, row, "copy_rop row");
    (*dev_proc(&mdev, close_device))((gx_device *)&mdev);
    return code;
}
예제 #2
0
/* Send the page to the printer. */
static int
atx_print_page(gx_device_printer *pdev, FILE *f, int max_width_bytes)
{
    /*
     * The page length command uses 16 bits to represent the length in
     * units of 0.01", so the maximum representable page length is 
     * 655.35", including the unprintable top and bottom margins.
     * Compute the maximum height of the printable area in pixels.
     */
    float top_bottom_skip = (pdev->HWMargins[1] + pdev->HWMargins[3]) / 72.0;
    int max_height = (int)(pdev->HWResolution[1] * 655 - top_bottom_skip);
    int height = min(pdev->height, max_height);
    int page_length_100ths =
	(int)ceil((height / pdev->HWResolution[1] + top_bottom_skip) * 100);
    gs_memory_t *mem = pdev->memory;
    int raster = gx_device_raster((gx_device *)pdev, true);
    byte *buf;
    /*
     * ATX_COMPRESSED_DATA only takes a 1-byte (word) count.
     * Thus no compressed scan line can take more than 510 bytes.
     */
    int compressed_raster = min(raster / 2, 510); /* require 50% compression */
    byte *compressed;
    int blank_lines, lnum;
    int code = 0;

    /* Enforce a minimum 3" page length. */
    if (page_length_100ths < 300)
	page_length_100ths = 300;
    buf = gs_alloc_bytes(mem, raster, "atx_print_page(buf)");
    compressed = gs_alloc_bytes(mem, compressed_raster,
				"atx_print_page(compressed)");
    if (buf == 0 || compressed == 0) {
	code = gs_note_error(gs_error_VMerror);
	goto done;
    }
    fput_atx_command(f, ATX_SET_PAGE_LENGTH, page_length_100ths);
    for (blank_lines = 0, lnum = 0; lnum < height; ++lnum) {
	byte *row;
	byte *end;
	int count;

	gdev_prn_get_bits(pdev, lnum, buf, &row);
	/* Find the end of the non-blank data. */
	for (end = row + raster; end > row && end[-1] == 0 && end[-2] == 0; )
	    end -= 2;
	if (end == row) {		/* blank line */
	    ++blank_lines;
	    continue;
	}
	if (blank_lines) {		/* skip vertically */
	    fput_atx_command(f, ATX_VERTICAL_TAB, blank_lines + 1);
	    blank_lines = 0;
	}
	/* Truncate the line to the maximum printable width. */
	if (end - row > max_width_bytes)
	    end = row + max_width_bytes;
	count = atx_compress(row, end - row, compressed, compressed_raster);
	if (count >= 0) {		/* compressed line */
	    /*
	     * Note that since compressed_raster can't exceed 510, count
	     * can't exceed 510 either.
	     */
	    fputs(ATX_COMPRESSED_DATA, f);
	    fputc(count / 2, f);
	    fwrite(compressed, 1, count, f);
	} else {			/* uncompressed line */
	    int num_bytes = end - row;

	    fput_atx_command(f, ATX_UNCOMPRESSED_DATA, num_bytes);
	    fwrite(row, 1, num_bytes, f);
	}
    }

#if 0	/**************** MAY NOT BE NEEDED ****************/
    /* Enforce the minimum page length, and skip any final blank lines. */
    {
	int paper_length = (int)(pdev->HWResolution[1] * 3 + 0.5);
	int printed_length = height - blank_lines;

	if (height > paper_length)
	    paper_length = height;
	if (printed_length < paper_length)
	    fput_atx_command(f, ATX_VERTICAL_TAB,
			     paper_length - printed_length + 1);
    }
#endif

    /* End the page. */
    fputs(ATX_END_PAGE, f);

 done:
    gs_free_object(mem, compressed, "atx_print_page(compressed)");
    gs_free_object(mem, buf, "atx_print_page(buf)");
    return code;
}
예제 #3
0
int
gs_shading_LfGt_fill_rectangle(const gs_shading_t * psh0, const gs_rect * rect,
			       const gs_fixed_rect * rect_clip,
			       gx_device * dev, gs_imager_state * pis)
{
    const gs_shading_LfGt_t * const psh = (const gs_shading_LfGt_t *)psh0;
    patch_fill_state_t pfs;
    const gs_shading_mesh_t *pshm = (const gs_shading_mesh_t *)psh;
    shade_coord_stream_t cs;
    shading_vertex_t *vertex = NULL;
    byte *color_buffer = NULL;
    patch_color_t **color_buffer_ptrs = NULL; /* non-const access to vertex[i].c */
    shading_vertex_t next;
    int per_row = psh->params.VerticesPerRow;
    patch_color_t *c, *cn; /* cn == next.c always, provides a non-contst access. */
    int i, code;

    if (VD_TRACE_TRIANGLE_PATCH && vd_allowed('s')) {
	vd_get_dc('s');
	vd_set_shift(0, 0);
	vd_set_scale(0.01);
	vd_set_origin(0, 0);
    }
    shade_init_fill_state((shading_fill_state_t *)&pfs,
			  (const gs_shading_t *)psh, dev, pis);
    pfs.Function = pshm->params.Function;
    pfs.rect = *rect_clip;
    code = init_patch_fill_state(&pfs);
    if (code < 0)
	goto out;
    reserve_colors(&pfs, &cn, 1); /* Can't fail. */
    next.c = cn;
    shade_next_init(&cs, (const gs_shading_mesh_params_t *)&psh->params,
		    pis);
    vertex = (shading_vertex_t *)
	gs_alloc_byte_array(pis->memory, per_row, sizeof(*vertex),
			    "gs_shading_LfGt_render");
    if (vertex == NULL) {
	code = gs_note_error(gs_error_VMerror);
	goto out;
    }
    color_buffer = gs_alloc_bytes(pis->memory, pfs.color_stack_step * per_row, "gs_shading_LfGt_fill_rectangle");
    if (color_buffer == NULL) {
	code = gs_note_error(gs_error_VMerror);
	goto out;
    }
    color_buffer_ptrs = (patch_color_t **)gs_alloc_bytes(pis->memory, 
			    sizeof(patch_color_t *) * per_row, "gs_shading_LfGt_fill_rectangle");
    if (color_buffer_ptrs == NULL) {
	code = gs_note_error(gs_error_VMerror);
	goto out;
    }
    /* CET 09-47K.PS SpecialTestJ02Test05 needs the color data alignment. */
    for (i = 0; i < per_row; ++i) {
	color_buffer_ptrs[i] = (patch_color_t *)(color_buffer + pfs.color_stack_step * i);
	vertex[i].c = color_buffer_ptrs[i];
	if ((code = Gt_next_vertex(pshm, &cs, &vertex[i], color_buffer_ptrs[i])) < 0)
	    goto out;
    }
    while (!seofp(cs.s)) {
	code = Gt_next_vertex(pshm, &cs, &next, cn);
	if (code < 0)
	    goto out;
	for (i = 1; i < per_row; ++i) {
	    code = Gt_fill_triangle(&pfs, &vertex[i - 1], &vertex[i], &next);
	    if (code < 0)
		goto out;
	    c = color_buffer_ptrs[i - 1];
	    vertex[i - 1] = next;
	    color_buffer_ptrs[i - 1] = cn;
	    next.c = cn = c;
	    code = Gt_next_vertex(pshm, &cs, &next, cn);
	    if (code < 0)
		goto out;
	    code = Gt_fill_triangle(&pfs, &vertex[i], &vertex[i - 1], &next);
	    if (code < 0)
		goto out;
	}
	c = color_buffer_ptrs[per_row - 1];
	vertex[per_row - 1] = next;
	color_buffer_ptrs[per_row - 1] = cn;
	next.c = cn = c;
    }
out:
    if (VD_TRACE_TRIANGLE_PATCH && vd_allowed('s'))
	vd_release_dc;
    gs_free_object(pis->memory, vertex, "gs_shading_LfGt_render");
    gs_free_object(pis->memory, color_buffer, "gs_shading_LfGt_render");
    gs_free_object(pis->memory, color_buffer_ptrs, "gs_shading_LfGt_render");
    release_colors(&pfs, pfs.color_stack, 1);
    if (term_patch_fill_state(&pfs))
	return_error(gs_error_unregistered); /* Must not happen. */
    if (pfs.icclink != NULL) gsicc_release_link(pfs.icclink);
    return code;
}
예제 #4
0
/* Send the page to the printer. */
static int
bj10e_print_page(gx_device_printer *pdev, FILE *prn_stream)
{	int line_size = gx_device_raster((gx_device *)pdev, 0);
        int xres = (int)pdev->x_pixels_per_inch;
        int yres = (int)pdev->y_pixels_per_inch;
        int mode = (yres == 180 ?
                        (xres == 180 ? 11 : 12) :
                        (xres == 180 ? 14 : 16));
        int bytes_per_column = (yres == 180) ? 3 : 6;
        int bits_per_column = bytes_per_column * 8;
        int skip_unit = bytes_per_column * 3;
        byte *in = (byte *)gs_malloc(pdev->memory, 8, line_size, "bj10e_print_page(in)");
        byte *out = (byte *)gs_malloc(pdev->memory, bits_per_column, line_size, "bj10e_print_page(out)");
        int lnum = 0;
        int skip = 0;
        int code = 0;
        int last_row = dev_print_scan_lines(pdev);
        int limit = last_row - bits_per_column;

        if ( in == 0 || out == 0 )
        {	code = gs_note_error(gs_error_VMerror);
                goto fin;
        }

        /* Initialize the printer. */
#ifdef USE_FACTORY_DEFAULTS
        /* Check for U.S. letter vs. A4 paper. */
        fwrite(( pdev->width / pdev->x_pixels_per_inch <= 8.4 ?
                "\033[K\002\000\000\044"	/*A4--DIP switch defaults*/ :
                "\033[K\002\000\004\044"	/*letter--factory defaults*/ ),
               1, 7, prn_stream);
#else
        fwrite("\033[K\002\000\000\044", 1, 7, prn_stream);
#endif

        /* Turn off automatic carriage return, otherwise we get line feeds. */
        fwrite("\0335\000", 1, 3, prn_stream);

        /* Set vertical spacing. */
        fwrite("\033[\\\004\000\000\000", 1, 7, prn_stream);
        fputc(yres & 0xff, prn_stream);
        fputc(yres >> 8, prn_stream);

        /* Set the page length.  This is the printable length, in inches. */
        fwrite("\033C\000", 1, 3, prn_stream);
        fputc((last_row + yres - 1)/yres, prn_stream);

        /* Transfer pixels to printer.  The last row we can print is defined
           by "last_row".  Only the bottom of the print head can print at the
           bottom margin, and so we align the final printing pass.  The print
           head is kept from moving below "limit", which is exactly one pass
           above the bottom margin.  Once it reaches this limit, we make our
           final printing pass of a full "bits_per_column" rows. */
        while ( lnum < last_row )
           {
                byte *in_data;
                byte *in_end = in + line_size;
                byte *out_beg = out;
                byte *out_end = out + bytes_per_column * pdev->width;
                byte *outl = out;
                int bnum;

                /* Copy 1 scan line and test for all zero. */
                code = gdev_prn_get_bits(pdev, lnum, in, &in_data);
                if ( code < 0 ) goto xit;
                /* The mem... or str... functions should be faster than */
                /* the following code, but all systems seem to implement */
                /* them so badly that this code is faster. */
                   {	register const long *zip = (const long *)in_data;
                        register int zcnt = line_size;
                        register const byte *zipb;
                        for ( ; zcnt >= 4 * sizeof(long); zip += 4, zcnt -= 4 * sizeof(long) )
                           {	if ( zip[0] | zip[1] | zip[2] | zip[3] )
                                        goto notz;
                           }
                        zipb = (const byte *)zip;
                        while ( --zcnt >= 0 )
                           {
                                if ( *zipb++ )
                                        goto notz;
                           }
                        /* Line is all zero, skip */
                        lnum++;
                        skip++;
                        continue;
notz:			;
                   }

                /* Vertical tab to the appropriate position.  Note here that
                   we make sure we don't move below limit. */
                if ( lnum > limit )
                    {	skip -= (lnum - limit);
                        lnum = limit;
                    }
                while ( skip > 255 )
                   {	fputs("\033J\377", prn_stream);
                        skip -= 255;
                   }
                if ( skip )
                        fprintf(prn_stream, "\033J%c", skip);

                /* If we've printed as far as "limit", then reset "limit"
                   to "last_row" for the final printing pass. */
                if ( lnum == limit )
                        limit = last_row;
                skip = 0;

                /* Transpose in blocks of 8 scan lines. */
                for ( bnum = 0; bnum < bits_per_column; bnum += 8 )
                   {	int lcnt = min(8, limit - lnum);
                        byte *inp = in;
                        byte *outp = outl;
                        lcnt = gdev_prn_copy_scan_lines(pdev,
                                lnum, in, lcnt * line_size);
                        if ( lcnt < 0 )
                           {	code = lcnt;
                                goto xit;
                           }
                        if ( lcnt < 8 )
                                memset(in + lcnt * line_size, 0,
                                       (8 - lcnt) * line_size);
                        for ( ; inp < in_end; inp++, outp += bits_per_column )
                           {	gdev_prn_transpose_8x8(inp, line_size,
                                        outp, bytes_per_column);
                           }
                        outl++;
                        lnum += lcnt;
                        skip += lcnt;
                   }

                /* Send the bits to the printer.  We alternate horizontal
                   skips with the data.  The horizontal skips are in units
                   of 1/120 inches, so we look at the data in groups of
                   3 columns, since 3/360 = 1/120, and 3/180 = 2/120.  */
                outl = out;
                do
                   {	int count;
                        int n;
                        byte *out_ptr;

                        /* First look for blank groups of columns. */
                        while(outl < out_end)
                           {	n = count = min(out_end - outl, skip_unit);
                                out_ptr = outl;
                                while ( --count >= 0 )
                                   {	if ( *out_ptr++ )
                                                break;
                                   }
                                if ( count >= 0 )
                                        break;
                                else
                                        outl = out_ptr;
                           }
                        if (outl >= out_end)
                                break;
                        if (outl > out_beg)
                           {	count = (outl - out_beg) / skip_unit;
                                if ( xres == 180 ) count <<= 1;
                                fprintf(prn_stream, "\033d%c%c",
                                        count & 0xff, count >> 8);
                           }

                        /* Next look for non-blank groups of columns. */
                        out_beg = outl;
                        outl += n;
                        while(outl < out_end)
                           {	n = count = min(out_end - outl, skip_unit);
                                out_ptr = outl;
                                while ( --count >= 0 )
                                   {	if ( *out_ptr++ )
                                                break;
                                   }
                                if ( count < 0 )
                                        break;
                                else
                                        outl += n;
                           }
                        count = outl - out_beg + 1;
                        fprintf(prn_stream, "\033[g%c%c%c",
                                count & 0xff, count >> 8, mode);
                        fwrite(out_beg, 1, count - 1, prn_stream);
                        out_beg = outl;
                        outl += n;
                   }
                while ( out_beg < out_end );

                fputc('\r', prn_stream);
           }
예제 #5
0
/*
 * Must be called by async device driver implementation (see gdevprna.h
 * under "Synchronizing the Instances"). This is the rendering loop, which
 * requires its own thread for as long as the device is open. This proc only
 * returns after the device is closed, or if the open failed. NB that an
 * open error leaves things in a state where the writer thread will not be
 * able to close since it's expecting the renderer to acknowledge its
 * requests before the writer can close.  Ergo, if this routine fails you'll
 * crash unless the caller fixes the problem & successfully retries this.
 */
int				/* rets 0 ok, -ve error code if open failed */
gdev_prn_async_render_thread(
                             gdev_prn_start_render_params * params
)
{
    gx_device_printer *const pwdev = params->writer_device;
    gx_device_printer *const prdev = pwdev->async_renderer;
    gx_page_queue_entry_t *entry;
    int code;

    /* Open device, but don't use default if user didn't override */
    if (prdev->printer_procs.open_render_device ==
          gx_default_open_render_device)
        code = gdev_prn_async_render_open(prdev);
    else
        code = (*prdev->printer_procs.open_render_device) (prdev);
    reinit_printer_into_renderer(prdev);

    /* The cmd list logic assumes reader's & writer's tile caches are same size */
    if (code >= 0 &&
          ((gx_device_clist *) pwdev)->writer.page_tile_cache_size !=
            ((gx_device_clist *) prdev)->writer.page_tile_cache_size) {
        gdev_prn_async_render_close_device(prdev);
        code = gs_note_error(gs_error_VMerror);
    }
    params->open_code = code;
    gx_semaphore_signal(params->open_semaphore);
    if (code < 0)
        return code;

    /* fake open, since not called by gs_opendevice */
    prdev->is_open = true;

    /* Successful open */
    while ((entry = gx_page_queue_start_dequeue(prdev->page_queue))
           && entry->action != GX_PAGE_QUEUE_ACTION_TERMINATE) {
        /* Force printer open again if it mysteriously closed. */
        /* This shouldn't ever happen, but... */
        if (!prdev->is_open) {
            if (prdev->printer_procs.open_render_device ==
                  gx_default_open_render_device)
                code = gdev_prn_async_render_open(prdev);
            else
                code = (*prdev->printer_procs.open_render_device) (prdev);
            reinit_printer_into_renderer(prdev);

            if (code >= 0) {
                prdev->is_open = true;
                gdev_prn_output_page((gx_device *) prdev, 0, true);
            }
        }
        if (prdev->is_open) {
            /* Force retrieved entry onto render device */
            ((gx_device_clist *) prdev)->common.page_info = entry->page_info;

            /* Set up device geometry */
            if (clist_setup_params((gx_device *) prdev) >= 0)
                /* Go this again, since setup_params may have trashed it */
                ((gx_device_clist *) prdev)->common.page_info = entry->page_info;

            /* Call appropriate renderer routine to deal w/buffer */
            /* Ignore status, since we don't know how to deal w/errors! */
            switch (entry->action) {

                case GX_PAGE_QUEUE_ACTION_FULL_PAGE:
                    (*dev_proc(prdev, output_page))((gx_device *) prdev,
                                                    entry->num_copies, true);
                    break;

                case GX_PAGE_QUEUE_ACTION_PARTIAL_PAGE:
                case GX_PAGE_QUEUE_ACTION_COPY_PAGE:
                    (*dev_proc(prdev, output_page))((gx_device *) prdev,
                                                    entry->num_copies, false);
                    break;
            }
            /*
             * gx_page_queue_finish_dequeue will close and free the band
             * list files, so we don't need to call clist_close_output_file.
             */
        }
        /* Finalize dequeue & free retrieved queue entry */
        gx_page_queue_finish_dequeue(entry);
    }

    /* Close device, but don't use default if user hasn't overriden. */
    /* Ignore status, since returning bad status means open failed */
    if (prdev->printer_procs.close_render_device ==
          gx_default_close_render_device)
        gdev_prn_async_render_close_device(prdev);
    else
        (*prdev->printer_procs.close_render_device)(prdev);

    /* undo fake open, since not called by gs_closedevice */
    prdev->is_open = false;

    /* Now that device is closed, acknowledge gx_page_queue_terminate */
    gx_page_queue_finish_dequeue(entry);

    return 0;
}
예제 #6
0
/* Common setup for encoding and decoding filters */
static int
bhc_setup(os_ptr op, stream_BHC_state * pbhcs)
{
    int code;
    int num_counts;
    int data[max_hc_length + 1 + 256 + max_zero_run + 1];
    uint dsize;
    int i;
    uint num_values, accum;
    ushort *counts;
    ushort *values;

    check_type(*op, t_dictionary);
    check_dict_read(*op);
    if ((code = dict_bool_param(op, "FirstBitLowOrder", false,
                                &pbhcs->FirstBitLowOrder)) < 0 ||
        (code = dict_int_param(op, "MaxCodeLength", 1, max_hc_length,
                               max_hc_length, &num_counts)) < 0 ||
        (code = dict_bool_param(op, "EndOfData", true,
                                &pbhcs->EndOfData)) < 0 ||
        (code = dict_uint_param(op, "EncodeZeroRuns", 2, 256,
                                256, &pbhcs->EncodeZeroRuns)) < 0 ||
    /* Note: the code returned from the following call */
    /* is actually the number of elements in the array. */
        (code = dict_int_array_param(imemory, op, "Tables", countof(data),
                                     data)) <= 0
        )
        return (code < 0 ? code : gs_note_error(e_rangecheck));
    dsize = code;
    if (dsize <= num_counts + 2)
        return_error(e_rangecheck);
    for (i = 0, num_values = 0, accum = 0; i <= num_counts;
         i++, accum <<= 1
        ) {
        int count = data[i];

        if (count < 0)
            return_error(e_rangecheck);
        num_values += count;
        accum += count;
    }
    if (dsize != num_counts + 1 + num_values ||
        accum != 1 << (num_counts + 1) ||
        pbhcs->EncodeZeroRuns >
        (pbhcs->EndOfData ? num_values - 1 : num_values)
        )
        return_error(e_rangecheck);
    for (; i < num_counts + 1 + num_values; i++) {
        int value = data[i];

        if (value < 0 || value >= num_values)
            return_error(e_rangecheck);
    }
    pbhcs->definition.counts = counts =
        (ushort *) ialloc_byte_array(num_counts + 1, sizeof(ushort),
                                     "bhc_setup(counts)");
    pbhcs->definition.values = values =
        (ushort *) ialloc_byte_array(num_values, sizeof(ushort),
                                     "bhc_setup(values)");
    if (counts == 0 || values == 0) {
        ifree_object(values, "bhc_setup(values)");
        ifree_object(counts, "bhc_setup(counts)");
        return_error(e_VMerror);
    }
    for (i = 0; i <= num_counts; i++)
        counts[i] = data[i];
    pbhcs->definition.counts = counts;
    pbhcs->definition.num_counts = num_counts;
    for (i = 0; i < num_values; i++)
        values[i] = data[i + num_counts + 1];
    pbhcs->definition.values = values;
    pbhcs->definition.num_values = num_values;
    return 0;
}
예제 #7
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;
}
예제 #8
0
int
gx_begin_image3_generic(gx_device * dev,
                        const gs_imager_state *pis, const gs_matrix *pmat,
                        const gs_image_common_t *pic, const gs_int_rect *prect,
                        const gx_drawing_color *pdcolor,
                        const gx_clip_path *pcpath, gs_memory_t *mem,
                        image3_make_mid_proc_t make_mid,
                        image3_make_mcde_proc_t make_mcde,
                        gx_image_enum_common_t **pinfo)
{
    const gs_image3_t *pim = (const gs_image3_t *)pic;
    gx_image3_enum_t *penum;
    gs_int_rect mask_rect, data_rect;
    gx_device *mdev = 0;
    gx_device *pcdev = 0;
    gs_image_t i_pixel, i_mask;
    gs_matrix mi_pixel, mi_mask, mat;
    gs_rect mrect;
    gs_int_point origin;
    int code;

    /* Validate the parameters. */
    if (pim->Height <= 0 || pim->MaskDict.Height <= 0)
        return_error(gs_error_rangecheck);
    switch (pim->InterleaveType) {
        default:
            return_error(gs_error_rangecheck);
        case interleave_chunky:
            if (pim->MaskDict.Width != pim->Width ||
                pim->MaskDict.Height != pim->Height ||
                pim->MaskDict.BitsPerComponent != pim->BitsPerComponent ||
                pim->format != gs_image_format_chunky
                )
                return_error(gs_error_rangecheck);
            break;
        case interleave_scan_lines:
            if (pim->MaskDict.Height % pim->Height != 0 &&
                pim->Height % pim->MaskDict.Height != 0
                )
                return_error(gs_error_rangecheck);
            /* falls through */
        case interleave_separate_source:
            if (pim->MaskDict.BitsPerComponent != 1)
                return_error(gs_error_rangecheck);
    }
    if (!check_image3_extent(pim->ImageMatrix.xx,
                             pim->MaskDict.ImageMatrix.xx) ||
        !check_image3_extent(pim->ImageMatrix.xy,
                             pim->MaskDict.ImageMatrix.xy) ||
        !check_image3_extent(pim->ImageMatrix.yx,
                             pim->MaskDict.ImageMatrix.yx) ||
        !check_image3_extent(pim->ImageMatrix.yy,
                             pim->MaskDict.ImageMatrix.yy)
        )
        return_error(gs_error_rangecheck);
    if ((code = gs_matrix_invert(&pim->ImageMatrix, &mi_pixel)) < 0 ||
        (code = gs_matrix_invert(&pim->MaskDict.ImageMatrix, &mi_mask)) < 0
        )
        return code;
    if (fabs(mi_pixel.tx - mi_mask.tx) >= 0.5 ||
        fabs(mi_pixel.ty - mi_mask.ty) >= 0.5
        )
        return_error(gs_error_rangecheck);
#ifdef DEBUG
    {
        /* Although the PLRM says that the Mask and Image *must* be the same size,  */
        /* Adobe CPSI (and other RIPS) ignore this and process anyway. Note that we */
        /* are not compatible if the Mask Height than the Data (pixel) Height. CPSI */
        /* de-interleaves the mask from the data image and stops at the Mask Height */
        /* Problem detected with Genoa 468-03 (part of file 468-01.ps)              */
        /*****           fixme: When Data Image Height > Mask Height            *****/
        gs_point ep, em;

        if ((code = gs_point_transform(pim->Width, pim->Height, &mi_pixel,
                                       &ep)) < 0 ||
            (code = gs_point_transform(pim->MaskDict.Width,
                                       pim->MaskDict.Height, &mi_mask,
                                       &em)) < 0
            )
            return code;
        if (fabs(ep.x - em.x) >= 0.5 || fabs(ep.y - em.y) >= 0.5)
            code = gs_error_rangecheck;	/* leave the check in for debug breakpoint */
    }
#endif /* DEBUG */
    penum = gs_alloc_struct(mem, gx_image3_enum_t, &st_image3_enum,
                            "gx_begin_image3");
    if (penum == 0)
        return_error(gs_error_VMerror);
    penum->num_components =
        gs_color_space_num_components(pim->ColorSpace);
    gx_image_enum_common_init((gx_image_enum_common_t *) penum,
                              (const gs_data_image_t *)pim,
                              &image3_enum_procs, dev,
                              1 + penum->num_components,
                              pim->format);
    /* Initialize pointers now in case we bail out. */
    penum->mask_data = 0;
    penum->pixel_data = 0;
    if (prect) {
        long lmw = pim->MaskDict.Width, lmh = pim->MaskDict.Height;

        data_rect = *prect;
        mask_rect.p.x = (int)(data_rect.p.x * lmw / pim->Width);
        mask_rect.p.y = (int)(data_rect.p.y * lmh / pim->Height);
        mask_rect.q.x = (int)((data_rect.q.x + pim->Width - 1) * lmw /
                              pim->Width);
        mask_rect.q.y = (int)((data_rect.q.y + pim->Height - 1) * lmh /
                              pim->Height);
    } else {
        mask_rect.p.x = mask_rect.p.y = 0;
        mask_rect.q.x = pim->MaskDict.Width;
        mask_rect.q.y = pim->MaskDict.Height;
        data_rect.p.x = data_rect.p.y = 0;
        data_rect.q.x = pim->Width;
        data_rect.q.y = pim->Height;
    }
    penum->mask_width = mask_rect.q.x - mask_rect.p.x;
    penum->mask_height = mask_rect.q.y - mask_rect.p.y;
    penum->mask_full_height = pim->MaskDict.Height;
    penum->mask_y = 0;
    penum->mask_skip = 0;
    penum->pixel_width = data_rect.q.x - data_rect.p.x;
    penum->pixel_height = data_rect.q.y - data_rect.p.y;
    penum->pixel_full_height = pim->Height;
    penum->pixel_y = 0;
    penum->mask_info = 0;
    penum->pixel_info = 0;
    if (pim->InterleaveType == interleave_chunky) {
        /* Allocate row buffers for the mask and pixel data. */
        penum->pixel_data =
            gs_alloc_bytes(mem,
                           (penum->pixel_width * pim->BitsPerComponent *
                            penum->num_components + 7) >> 3,
                           "gx_begin_image3(pixel_data)");
        penum->mask_data =
            gs_alloc_bytes(mem, (penum->mask_width + 7) >> 3,
                           "gx_begin_image3(mask_data)");
        if (penum->pixel_data == 0 || penum->mask_data == 0) {
            code = gs_note_error(gs_error_VMerror);
            goto out1;
        }
    }
예제 #9
0
/* Send the page to the file. */
static int
jbig2_print_page(gx_device_printer * pdev, FILE * prn_stream)
{
    gx_device_jbig2 *jdev = (gx_device_jbig2 *) pdev;
    gs_memory_t *mem = jdev->memory;
    int line_size = gdev_mem_bytes_per_scan_line((gx_device *) pdev);
    byte *in = gs_alloc_bytes(mem, line_size, "jbig2_print_page(in)");
    byte *fbuf = 0;
    uint fbuf_size;
    byte *jbuf = 0;
    uint jbuf_size;
    int lnum;
    int code = 0;
    stream_jbig2encode_state state;
    stream fstrm, cstrm;

    if (in == 0) {
        code = gs_note_error(gs_error_VMerror);
        goto fail;
    }
    /* Create the jbig2encode state. */
    s_init_state((stream_state *)&state, &s_jbig2encode_template, 0);
    if (state.templat->set_defaults)
        (*state.templat->set_defaults) ((stream_state *) & state);
    state.width = jdev->width;
    state.height = jdev->height;
    /* Set up the streams. */
    fbuf_size = max(512 /* arbitrary */ , state.templat->min_out_size);
    jbuf_size = state.templat->min_in_size;
    if ((fbuf = gs_alloc_bytes(mem, fbuf_size, "jbig2_print_page(fbuf)")) == 0 ||
        (jbuf = gs_alloc_bytes(mem, jbuf_size, "jbig2_print_page(jbuf)")) == 0
        ) {
        code = gs_note_error(gs_error_VMerror);
        goto done;
    }
    s_init(&fstrm, mem);
    swrite_file(&fstrm, prn_stream, fbuf, fbuf_size);
    s_init(&cstrm, mem);
    s_std_init(&cstrm, jbuf, jbuf_size, &s_filter_write_procs,
               s_mode_write);
    cstrm.state = (stream_state *) & state;
    cstrm.procs.process = state.templat->process;
    cstrm.strm = &fstrm;
    if (state.templat->init)
        (*state.templat->init) (cstrm.state);

    /* Copy the data to the output. */
    for (lnum = 0; lnum < jdev->height; ++lnum) {
        byte *data;
        uint ignore_used;

        if (cstrm.end_status) {
            code = gs_note_error(gs_error_ioerror);
            goto done;
        }
        gdev_prn_get_bits(pdev, lnum, in, &data);
        sputs(&cstrm, data, state.stride, &ignore_used);
    }

    /* Wrap up. */
    sclose(&cstrm);
    sflush(&fstrm);
  done:
    gs_free_object(mem, jbuf, "jbig2_print_page(jbuf)");
    gs_free_object(mem, fbuf, "jbig2_print_page(fbuf)");
    gs_free_object(mem, in, "jbig2_print_page(in)");
    return code;
  fail:
    gs_free_object(mem, in, "jbig2_print_page(in)");
    return code;
}
예제 #10
0
/*
 * Create an ICCBased color space object (internal).  The client must write
 * the profile data on *ppcstrm.
 */
static int
pdf_make_iccbased(gx_device_pdf *pdev, cos_array_t *pca, int ncomps,
		  const gs_range *prange /*[4]*/,
		  const gs_color_space *pcs_alt,
		  cos_stream_t **ppcstrm,
		  const gs_range_t **pprange /* if scaling is needed */)

{
    cos_value_t v;
    int code;
    cos_stream_t * pcstrm = 0;
    cos_array_t * prngca = 0;
    bool std_ranges = true;
    bool scale_inputs = false;
    int i;

    /* Check the ranges. */
    if (pprange)
	*pprange = 0;
    for (i = 0; i < ncomps; ++i) {
	double rmin = prange[i].rmin, rmax = prange[i].rmax;

	if (rmin < 0.0 || rmax > 1.0) {
	    /* We'll have to scale the inputs.  :-( */
	    if (pprange == 0)
		return_error(gs_error_rangecheck); /* scaling not allowed */
	    *pprange = prange;
	    scale_inputs = true;
	}
	else if (rmin > 0.0 || rmax < 1.0)
	    std_ranges = false;
    }

    /* ICCBased color spaces are essentially copied to the output. */
    if ((code = cos_array_add(pca, cos_c_string_value(&v, "/ICCBased"))) < 0)
	return code;

    /* Create a stream for the output. */
    if ((pcstrm = cos_stream_alloc(pdev, "pdf_make_iccbased(stream)")) == 0) {
	code = gs_note_error(gs_error_VMerror);
	goto fail;
    }

    /* Indicate the number of components. */
    code = cos_dict_put_c_key_int(cos_stream_dict(pcstrm), "/N", ncomps);
    if (code < 0)
	goto fail;

    /* Indicate the range, if needed. */
    if (!std_ranges && !scale_inputs) {
	code = pdf_cie_add_ranges(cos_stream_dict(pcstrm), prange, ncomps, true);
	if (code < 0)
	    goto fail;
    }

    /* Output the alternate color space, if necessary. */
    switch (gs_color_space_get_index(pcs_alt)) {
    case gs_color_space_index_DeviceGray:
    case gs_color_space_index_DeviceRGB:
    case gs_color_space_index_DeviceCMYK:
	break;			/* implicit (default) */
    default:
	if ((code = pdf_color_space(pdev, &v, NULL, pcs_alt,
				    &pdf_color_space_names, false)) < 0 ||
	    (code = cos_dict_put_c_key(cos_stream_dict(pcstrm), "/Alternate",
				       &v)) < 0
	    )
	    goto fail;
    }

    /* Wrap up. */
    if ((code = cos_array_add_object(pca, COS_OBJECT(pcstrm))) < 0)
	goto fail;
    *ppcstrm = pcstrm;
    return code;
 fail:
    if (prngca)
	COS_FREE(prngca, "pdf_make_iccbased(Range)");
    if (pcstrm)
	COS_FREE(pcstrm, "pdf_make_iccbased(stream)");
    return code;
}
예제 #11
0
/* Process a buffer of PCL XL commands. */
int
px_process(px_parser_state_t * st, px_state_t * pxs, stream_cursor_read * pr)
{
    const byte *orig_p = pr->ptr;
    const byte *next_p = orig_p;        /* start of data not copied to saved */
    const byte *p;
    const byte *rlimit;
    px_value_t *sp = &st->stack[st->stack_count];

#define stack_limit &st->stack[max_stack - 1]
    gs_memory_t *memory = st->memory;
    int code = 0;
    uint left;
    uint min_left;
    px_tag_t tag;
    const px_tag_syntax_t *syntax = 0;

    st->args.parser = st;
    st->parent_operator_count = 0;      /* in case of error */
    /* Check for leftover data from the previous call. */
  parse:if (st->saved_count) { /* Fill up the saved buffer so we can make progress. */
        int move = min(sizeof(st->saved) - st->saved_count,
                       pr->limit - next_p);

        memcpy(&st->saved[st->saved_count], next_p + 1, move);
        next_p += move;
        p = st->saved - 1;
        rlimit = p + st->saved_count + move;
    } else {                    /* No leftover data, just read from the input. */
        p = next_p;
        rlimit = pr->limit;
    }
  top:if (st->data_left) {     /* We're in the middle of reading an array or data block. */
        if (st->data_proc) {    /* This is a data block. */
            uint avail = min(rlimit - p, st->data_left);
            uint used;

            st->args.source.available = avail;
            st->args.source.data = p + 1;
            code = (*st->data_proc) (&st->args, pxs);
            /* If we get a 'remap_color' error, it means we are dealing with a
             * pattern, and the device supports high level patterns. So we must
             * use our high level pattern implementation.
             */
            if (code == gs_error_Remap_Color) {
                code = px_high_level_pattern(pxs->pgs);
                code = (*st->data_proc) (&st->args, pxs);
            }
            used = st->args.source.data - (p + 1);
#ifdef DEBUG
            if (gs_debug_c('I')) {
                px_value_t data_array;

                data_array.type = pxd_ubyte;
                data_array.value.array.data = p + 1;
                data_array.value.array.size = used;
                trace_array_data(pxs->memory, "data:", &data_array);
            }
#endif
            p = st->args.source.data - 1;
            st->data_left -= used;
            if (code < 0) {
                st->args.source.position = 0;
                goto x;
            } else if ((code == pxNeedData)
                       || (code == pxPassThrough && st->data_left != 0)) {
                code = 0;       /* exit for more data */
                goto x;
            } else {
                st->args.source.position = 0;
                st->data_proc = 0;
                if (st->data_left != 0) {
                    code = gs_note_error(errorExtraData);
                    goto x;
                }
                clear_stack();
            }
        } else {                /* This is an array. */
            uint size = sp->value.array.size;
            uint scale = value_size(sp);
            uint nbytes = size * scale;
            byte *dest =
                (byte *) sp->value.array.data + nbytes - st->data_left;

            left = rlimit - p;
            if (left < st->data_left) { /* We still don't have enough data to fill the array. */
                memcpy(dest, p + 1, left);
                st->data_left -= left;
                p = rlimit;
                code = 0;
                goto x;
            }
            /* Complete the array and continue parsing. */
            memcpy(dest, p + 1, st->data_left);
            trace_array(memory, sp);
            p += st->data_left;
        }
        st->data_left = 0;
    } else if (st->data_proc) { /* An operator is awaiting data. */
        /* Skip white space until we find some. */
        code = 0;               /* in case we exit */
        /* special case - VendorUnique has a length attribute which
           we've already parsed and error checked */
        if (st->data_proc == pxVendorUnique) {
            st->data_left =
                st->stack[st->attribute_indices[pxaVUDataLength]].value.i;
            goto top;
        } else {
            while ((left = rlimit - p) != 0) {
                switch ((tag = p[1])) {
                case pxtNull:
                case pxtHT:
                case pxtLF:
                case pxtVT:
                case pxtFF:
                case pxtCR:
                    ++p;
                    continue;
                case pxt_dataLength:
                    if (left < 5)
                        goto x; /* can't look ahead */
                    st->data_left = get_uint32(st, p + 2);
                    if_debug2m('i', memory, "tag=  0x%2x  data, length %u\n",
                               p[1], st->data_left);
                    p += 5;
                    goto top;
                case pxt_dataLengthByte:
                    if (left < 2)
                        goto x; /* can't look ahead */
                    st->data_left = p[2];
                    if_debug2m('i', memory, "tag=  0x%2x  data, length %u\n",
                               p[1], st->data_left);
                    p += 2;
                    goto top;
                default:
                    {
                        code = gs_note_error(errorMissingData);
                        goto x;
                    }
                }
            }
        }
    }
    st->args.source.position = 0;
    st->args.source.available = 0;
    while ((left = rlimit - p) != 0 &&
           left >= (min_left = (syntax = &tag_syntax[tag = p[1]])->min_input)
        ) {
        int count;

#ifdef DEBUG
        if (gs_debug_c('i')) {
            dmprintf1(memory, "tag=  0x%02x  ", tag);
            if (tag == pxt_attr_ubyte || tag == pxt_attr_uint16) {
                px_attribute_t attr =
                    (tag == pxt_attr_ubyte ? p[2] : get_uint16(st, p + 2));
                const char *aname = px_attribute_names[attr];

                if (aname)
                    dmprintf1(memory, "   @%s\n", aname);
                else
                    dmprintf1(memory, "   attribute %u ???\n", attr);
            } else {
                const char *format;
                const char *tname;
                bool operator = false;

                if (tag < 0x40)
                    format = "%s\n", tname = px_tag_0_names[tag];
                else if (tag < 0xc0)
                    format = "%s", tname = px_operator_names[tag - 0x40],
                        operator = true;
                else {
                    tname = px_tag_c0_names[tag - 0xc0];
                    if (tag < 0xf0)
                        format = "      %s";    /* data values follow */
                    else
                        format = "%s\n";
                }
                if (tname) {
                    dmprintf1(memory, format, tname);
                    if (operator)
                        dmprintf1(memory, " (%ld)\n", st->operator_count + 1);
                } else
                    dmputs(memory, "???\n");
            }
        }
#endif
        if ((st->macro_state & syntax->state_mask) != syntax->state_value) {
            /*
             * We should probably distinguish here between
             * out-of-context operators and illegal tags, but it's too
             * much trouble.
             */
            code = gs_note_error(errorIllegalOperatorSequence);
            if (tag >= 0x40 && tag < 0xc0)
                st->last_operator = tag;
            goto x;
        }
        st->macro_state ^= syntax->state_transition;
        switch (tag >> 3) {
            case 0:
                switch (tag) {
                    case pxtNull:
                        ++p;
                        continue;
                    default:
                        break;
                }
                break;
            case 1:
                switch (tag) {
                    case pxtHT:
                    case pxtLF:
                    case pxtVT:
                    case pxtFF:
                    case pxtCR:
                        ++p;
                        continue;
                    default:
                        break;
                }
                break;
            case 3:
                if (tag == pxt1b) {     /* ESC *//* Check for UEL */
                    if (memcmp(p + 1, "\033%-12345X", min(left, 9)))
                        break;  /* not UEL, error */
                    if (left < 9)
                        goto x; /* need more data */
                    p += 9;
                    code = e_ExitLanguage;
                    goto x;
                }
                break;
            case 4:
                switch (tag) {
                    case pxtSpace:
                        /* break; will error, compatible with lj */
                        /* ++p;continue; silently ignores the space */
                        ++p;
                        continue;
                    default:
                        break;
                }
                break;
            case 8:
            case 9:
            case 10:
            case 11:
            case 12:
            case 13:
            case 14:
            case 15:
            case 16:
            case 17:
            case 18:
            case 19:
            case 20:
            case 21:
            case 22:
            case 23:
                /* Operators */
                /* Make sure that we have all the required attributes, */
                /* and no attributes that are neither required nor */
                /* optional.  (It's up to the operator to make any */
                /* more precise checks than this. */
                st->operator_count++;
                /* if this is a passthrough operator we have to tell
                   the passthrough module if this operator was
                   preceded by another passthrough operator or a
                   different xl operator */
                if (tag == pxtPassThrough) {
                    pxpcl_passthroughcontiguous(st->last_operator == tag);
                } else if (st->last_operator == pxtPassThrough) {
                    pxpcl_endpassthroughcontiguous(pxs);
                }

                st->last_operator = tag;
                {
                    const px_operator_definition_t *pod =
                        &px_operator_definitions[tag - 0x40];
                    int left = sp - st->stack;
                    const byte /*px_attribute_t */  * pal = pod->attrs;
                    px_value_t **ppv = st->args.pv;
                    bool required = true;
                    code = 0;
                    /*
                     * Scan the attributes.  Illegal attributes take priority
                     * over missing attributes, which in turn take priority
                     * over illegal data types.
                     */
                    for (;; ++pal, ++ppv) {
                        px_attribute_t attr = *pal;
                        uint index;

                        if (!attr) {    /*
                                         * We've reached the end of either the required or
                                         * the optional attribute list.
                                         */
                            if (!required)
                                break;
                            required = false;
                            --ppv;      /* cancel incrementing */
                            continue;
                        }
                        if ((index = st->attribute_indices[attr]) == 0) {
                            if (required)
                                code = gs_note_error(errorMissingAttribute);
                            else
                                *ppv = 0;
                        } else {        /* Check the attribute data type and value. */
                            px_value_t *pv = *ppv = &st->stack[index];
                            const px_attr_value_type_t *pavt =
                                &px_attr_value_types[attr];
                            int acode;

                            if ((~pavt->mask & pv->type &
                                 (pxd_structure | pxd_representation)) ||
                                (pavt->mask == (pxd_scalar | pxd_ubyte) &&
                                 (pv->value.i < 0
                                  || pv->value.i > pavt->limit))
                                ) {
                                if (code >= 0)
                                    code =
                                        gs_note_error
                                        (errorIllegalAttributeDataType);
                            }
                            if (pavt->proc != 0
                                && (acode = (*pavt->proc) (pv)) < 0) {
                                if (code >= 0)
                                    code = acode;
                            }
                            --left;
                        }
                    }

                    /* Make sure there are no attributes left over. */
                    if (left)
                        code = gs_note_error(errorIllegalAttribute);
                    if (code >= 0) {
                        st->args.source.phase = 0;
                        code = (*pod->proc) (&st->args, pxs);
                        /* If we get a 'remap_color' error, it means we are dealing with a
                         * pattern, and the device supports high level patterns. So we must
                         * use our high level pattern implementation.
                         */
                        if (code == gs_error_Remap_Color) {
                            code = px_high_level_pattern(pxs->pgs);
                            if (code < 0)
                                goto x;
                            code = (*pod->proc) (&st->args, pxs);
                        }
                    }
                    if (code < 0)
                        goto x;
                    /* Check whether the operator wanted source data. */
                    if (code == pxNeedData) {
                        if (!pxs->data_source_open) {
                            code = gs_note_error(errorDataSourceNotOpen);
                            goto x;
                        }
                        st->data_proc = pod->proc;
                        ++p;
                        goto top;
                    }
                }
                clear_stack();
                ++p;
                continue;
            case 24:
                sp[1].type = pxd_scalar;
                count = 1;
                goto data;
            case 26:
                sp[1].type = pxd_xy;
                count = 2;
                goto data;
            case 28:
                sp[1].type = pxd_box;
                count = 4;
                goto data;
                /* Scalar, point, and box data */
              data:{
                    int i;

                    if (sp == stack_limit) {
                        code = gs_note_error(errorInternalOverflow);
                        goto x;
                    }
                    ++sp;
                    sp->attribute = 0;
                    p += 2;
#ifdef DEBUG
#  define trace_scalar(mem, format, cast, alt)\
                  if ( gs_debug_c('i') )\
                    trace_data(mem, format, cast, sp->value.alt, count)
#else
#  define trace_scalar(mem, format, cast, alt) DO_NOTHING
#endif
                    switch (tag & 7) {
                        case pxt_ubyte & 7:
                            sp->type |= pxd_ubyte;
                            for (i = 0; i < count; ++p, ++i)
                                sp->value.ia[i] = *p;
                          dux:trace_scalar(pxs->memory, " %lu", ulong,
                                         ia);
                            --p;
                            continue;
                        case pxt_uint16 & 7:
                            sp->type |= pxd_uint16;
                            for (i = 0; i < count; p += 2, ++i)
                                sp->value.ia[i] = get_uint16(st, p);
                            goto dux;
                        case pxt_uint32 & 7:
                            sp->type |= pxd_uint32;
                            for (i = 0; i < count; p += 4, ++i)
                                sp->value.ia[i] = get_uint32(st, p);
                            goto dux;
                        case pxt_sint16 & 7:
                            sp->type |= pxd_sint16;
                            for (i = 0; i < count; p += 2, ++i)
                                sp->value.ia[i] = get_sint16(st, p);
                          dsx:trace_scalar(pxs->memory, " %ld", long,
                                         ia);
                            --p;
                            continue;
                        case pxt_sint32 & 7:
                            sp->type |= pxd_sint32;
                            for (i = 0; i < count; p += 4, ++i)
                                sp->value.ia[i] = get_sint32(st, p);
                            goto dsx;
                        case pxt_real32 & 7:
                            sp->type |= pxd_real32;
                            for (i = 0; i < count; p += 4, ++i)
                                sp->value.ra[i] = get_real32(st, p);
                            trace_scalar(pxs->memory, " %g", double, ra);

                            --p;
                            continue;
                        default:
                            break;
                    }
                }
                break;
            case 25:
                /* Array data */
                {
                    const byte *dp;
                    uint nbytes;

                    if (sp == stack_limit) {
                        code = gs_note_error(errorInternalOverflow);
                        goto x;
                    }
                    switch (p[2]) {
                        case pxt_ubyte:
                            sp[1].value.array.size = p[3];
                            dp = p + 4;
                            break;
                        case pxt_uint16:
                            if (left < 4) {
                                if_debug0m('i', memory, "...\n");
                                /* Undo the state transition. */
                                st->macro_state ^= syntax->state_transition;
                                goto x;
                            }
                            sp[1].value.array.size = get_uint16(st, p + 3);
                            dp = p + 5;
                            break;
                        default:
                            st->last_operator = tag;    /* for error message */
                            code = gs_note_error(errorIllegalTag);
                            goto x;
                    }
                    nbytes = sp[1].value.array.size;
                    if_debug1m('i', memory, "[%u]\n", sp[1].value.array.size);
                    switch (tag) {
                        case pxt_ubyte_array:
                            sp[1].type = pxd_array | pxd_ubyte;
                          array:++sp;
                            if (st->big_endian)
                                sp->type |= pxd_big_endian;
                            sp->value.array.data = dp;
                            sp->attribute = 0;
                            /* Check whether we have enough data for the entire */
                            /* array. */
                            if (rlimit + 1 - dp < nbytes) {     /* Exit now, continue reading when we return. */
                                uint avail = rlimit + 1 - dp;

                                code = px_save_array(sp, pxs, "partial array",
                                                     avail);
                                if (code < 0)
                                    goto x;
                                sp->type |= pxd_on_heap;
                                st->data_left = nbytes - avail;
                                st->data_proc = 0;
                                p = rlimit;
                                goto x;
                            }
                            p = dp + nbytes - 1;
                            trace_array(memory, sp);
                            continue;
                        case pxt_uint16_array:
                            sp[1].type = pxd_array | pxd_uint16;
                          a16:nbytes <<= 1;
                            goto array;
                        case pxt_uint32_array:
                            sp[1].type = pxd_array | pxd_uint32;
                          a32:nbytes <<= 2;
                            goto array;
                        case pxt_sint16_array:
                            sp[1].type = pxd_array | pxd_sint16;
                            goto a16;
                        case pxt_sint32_array:
                            sp[1].type = pxd_array | pxd_sint32;
                            goto a32;
                        case pxt_real32_array:
                            sp[1].type = pxd_array | pxd_real32;
                            goto a32;
                        default:
                            break;
                    }
                    break;
                }
                break;
            case 31:
                {
                    px_attribute_t attr;
                    const byte *pnext;

                    switch (tag) {
                        case pxt_attr_ubyte:
                            attr = p[2];
                            pnext = p + 2;
                            goto a;
                        case pxt_attr_uint16:
                            attr = get_uint16(st, p + 2);
                            pnext = p + 3;
                          a:if (attr >=
                                px_attribute_next)
                                break;
                            /*
                             * We could check the attribute value type here, but
                             * in order to match the behavior of the H-P printers,
                             * we don't do it until we see the operator.
                             *
                             * It is legal to specify the same attribute more than
                             * once; the last value has priority.  If this happens,
                             * since the order of attributes doesn't matter, we can
                             * just replace the former value on the stack.
                             */
                            sp->attribute = attr;
                            if (st->attribute_indices[attr] != 0) {
                                px_value_t *old_sp =
                                    &st->stack[st->attribute_indices[attr]];
                                /* If the old value is on the heap, free it. */
                                if (old_sp->type & pxd_on_heap)
                                    gs_free_object(memory,
                                                   (void *)old_sp->value.
                                                   array.data,
                                                   "old value for duplicate attribute");
                                *old_sp = *sp--;
                            } else
                                st->attribute_indices[attr] = sp - st->stack;
                            p = pnext;
                            continue;
                        case pxt_dataLength:
                            /*
                             * Unexpected data length operators are normally not
                             * allowed, but there might be a zero-length data
                             * block immediately following a zero-size image,
                             * which doesn't ask for any data.
                             */
                            if (uint32at(p + 2, true /*arbitrary */ ) == 0) {
                                p += 5;
                                continue;
                            }
                            break;
                        case pxt_dataLengthByte:
                            /* See the comment under pxt_dataLength above. */
                            if (p[2] == 0) {
                                p += 2;
                                continue;
                            }
                            break;
                        default:
                            break;
                    }
                }
                break;
            default:
                break;
        }
        /* Unknown tag value.  Report an error. */
        st->last_operator = tag;        /* for error message */
        code = gs_note_error(errorIllegalTag);
        break;
    }
  x:                           /* Save any leftover input. */
    left = rlimit - p;
    if (rlimit != pr->limit) {  /* We were reading saved input. */
        if (left <= next_p - orig_p) {  /* We finished reading the previously saved input. */
            /* Continue reading current input, unless we got an error. */
            p = next_p -= left;
            rlimit = pr->limit;
            st->saved_count = 0;
            if (code >= 0)
                goto parse;
        } else {                /* There's still some previously saved input left over. */
            memmove(st->saved, p + 1, st->saved_count = left);
            p = next_p;
            rlimit = pr->limit;
            left = rlimit - p;
        }
    }
    /* Except in case of error, save any remaining input. */
    if (code >= 0) {
        if (left + st->saved_count > sizeof(st->saved)) {       /* Fatal error -- shouldn't happen! */
            code = gs_note_error(errorInternalOverflow);
            st->saved_count = 0;
        } else {
            memcpy(&st->saved[st->saved_count], p + 1, left);
            st->saved_count += left;
            p = rlimit;
        }
    }
    pr->ptr = p;
    st->stack_count = sp - st->stack;
    /* Move to the heap any arrays whose data was being referenced */
    /* directly in the input buffer. */
    for (; sp > st->stack; --sp)
        if ((sp->type & (pxd_array | pxd_on_heap)) == pxd_array) {
            int code = px_save_array(sp, pxs, "px stack array to heap",
                                     sp->value.array.size * value_size(sp));

            if (code < 0)
                break;
            sp->type |= pxd_on_heap;
        }
    if (code < 0 && syntax != 0) {      /* Undo the state transition. */
        st->macro_state ^= syntax->state_transition;
    }
    return code;
}
예제 #12
0
/* internal variables. */
static int
win_pr2_read_user_settings(gx_device_win_pr2 * wdev, gs_param_list * plist)
{
    gs_param_dict dict;
    gs_param_string docn = { 0 };
    const char* dict_name = "UserSettings";
    const char* param_name = "";
    int code = 0;
    int ecode = 0;

    switch (code = param_begin_read_dict(plist, dict_name, &dict, false)) {
	default:
	    param_signal_error(plist, dict_name, code);
	    return code;
	case 1:
	    break;
	case 0:
	    {
		gs_param_int_array ia;
		
		BEGIN_ARRAY_PARAM(param_read_int_array, "DocumentRange", ia, 2, ia)
		if ((ia.data[0] < 0) ||
		    (ia.data[1] < 0) ||
		    (ia.data[0] > ia.data[1]))
		    ecode = gs_note_error(gs_error_rangecheck);
		wdev->doc_page_begin = ia.data[0];
		wdev->doc_page_end = ia.data[1];
		END_ARRAY_PARAM(ia, doc_range_error)
		
		BEGIN_ARRAY_PARAM(param_read_int_array, "SelectedRange", ia, 2, ia)
		if ((ia.data[0] < 0) ||
		    (ia.data[1] < 0) ||
		    (ia.data[0] > ia.data[1]))
		    ecode = gs_note_error(gs_error_rangecheck);
		wdev->user_page_begin = ia.data[0];
		wdev->user_page_end = ia.data[1];
		END_ARRAY_PARAM(ia, sel_range_error)
		
		param_read_int(dict.list, "Copies", &wdev->user_copies);
		param_read_int(dict.list, "Paper", &wdev->user_paper);
		param_read_int(dict.list, "Orientation", &wdev->user_orient);
		param_read_int(dict.list, "Color", &wdev->user_color);
		param_read_int(dict.list, "MaxResolution", &wdev->max_dpi);
		
		switch (code = param_read_string(dict.list, (param_name = "DocumentName"), &docn)) {
		    case 0:
			if (docn.size < sizeof(wdev->doc_name))
			    break;
			code = gs_error_rangecheck;
			/* fall through */
		    default:
			ecode = code;
			param_signal_error(plist, param_name, ecode);
			/* fall through */
		    case 1:
			docn.data = 0;
			break;
		}
		
		param_end_read_dict(plist, dict_name, &dict);
		
		if (docn.data) {
		    memcpy(wdev->doc_name, docn.data, docn.size);
		    wdev->doc_name[docn.size] = 0;
		}
		
		wdev->print_copies = 1;
		
		if (wdev->win32_hdevmode) {
		    LPDEVMODE devmode = (LPDEVMODE) GlobalLock(wdev->win32_hdevmode);
		    if (devmode) {
			devmode->dmCopies = wdev->user_copies;
			devmode->dmPaperSize = wdev->user_paper;
			devmode->dmOrientation = wdev->user_orient;
			devmode->dmColor = wdev->user_color;
			GlobalUnlock(wdev->win32_hdevmode);
		    }
		}
	    }
	    break;
    }

    return code;
}
예제 #13
0
int
fn_build_sub_function(i_ctx_t *i_ctx_p, const ref * op, gs_function_t ** ppfn,
    int depth, gs_memory_t *mem, const float *shading_domain, const int num_inputs)
{
    int j, code, type;
    uint i;
    gs_function_params_t params;

    if (depth > MAX_SUB_FUNCTION_DEPTH)
        return_error(gs_error_limitcheck);
    check_type(*op, t_dictionary);
    code = dict_int_param(op, "FunctionType", 0, max_int, -1, &type);
    if (code < 0)
        return code;
    for (i = 0; i < build_function_type_table_count; ++i)
        if (build_function_type_table[i].type == type)
            break;
    if (i == build_function_type_table_count)
        return_error(gs_error_rangecheck);
    /* Collect parameters common to all function types. */
    params.Domain = 0;
    params.Range = 0;
    code = fn_build_float_array(op, "Domain", true, true, &params.Domain, mem);
    if (code < 0) {
        gs_errorinfo_put_pair_from_dict(i_ctx_p, op, "Domain");
        goto fail;
    }
    params.m = code >> 1;
    for (j = 0; j < params.m << 1; j += 2) {
        if (params.Domain[j] >= params.Domain[j + 1]) {
          code = gs_note_error(gs_error_rangecheck);
          gs_errorinfo_put_pair_from_dict(i_ctx_p, op, "Domain");
          goto fail;
        }
    }
    if (shading_domain) {
        /* Each function dictionary's domain must be a superset of that of
         * the shading dictionary. PLRM3 p.265. CET 12-14c. We do this check
         * here because Adobe checks Domain before checking other parameters.
         */
        if (num_inputs != params.m)
            code = gs_note_error(gs_error_rangecheck);
        for (j = 0; j < 2*num_inputs && code >= 0; j += 2) {
            if (params.Domain[j] > shading_domain[j] ||
                params.Domain[j+1] < shading_domain[j+1]
               ) {
                code = gs_note_error(gs_error_rangecheck);
            }
        }
        if (code < 0) {
            gs_errorinfo_put_pair_from_dict(i_ctx_p, op, "Domain");
            goto fail;
        }
    }
    code = fn_build_float_array(op, "Range", false, true, &params.Range, mem);
    if (code < 0)
        goto fail;
    params.n = code >> 1;
    /* Finish building the function. */
    /* If this fails, it will free all the parameters. */
    return (*build_function_type_table[i].proc)
        (i_ctx_p, op, &params, depth + 1, ppfn, mem);
fail:
    gs_free_const_object(mem, params.Range, "Range");
    gs_free_const_object(mem, params.Domain, "Domain");
    return code;
}
예제 #14
0
/* <in1> ... <function_struct> %execfunction <out1> ... */
int
zexecfunction(i_ctx_t *i_ctx_p)
{
    os_ptr op = osp;

        /*
         * Since this operator's name begins with %, the name is not defined
         * in systemdict.  The only place this operator can ever appear is
         * in the execute-only closure created by .buildfunction.
         * Therefore, in principle it is unnecessary to check the argument.
         * However, we do a little checking anyway just on general
         * principles.  Note that since the argument may be an instance of
         * any subclass of gs_function_t, we currently have no way to check
         * its type.
         */
    if (!r_is_struct(op) ||
        !r_has_masked_attrs(op, a_executable | a_execute, a_executable | a_all)
        )
        return_error(gs_error_typecheck);
    {
        gs_function_t *pfn = (gs_function_t *) op->value.pstruct;
        int m = pfn->params.m, n = pfn->params.n;
        int diff = n - (m + 1);

        if (diff > 0)
            check_ostack(diff);
        {
            float params[20];	/* arbitrary size, just to avoid allocs */
            float *in;
            float *out;
            int code = 0;

            if (m + n <= countof(params)) {
                in = params;
            } else {
                in = (float *)ialloc_byte_array(m + n, sizeof(float),
                                                "%execfunction(in/out)");
                if (in == 0)
                    code = gs_note_error(gs_error_VMerror);
            }
            out = in + m;
            if (code < 0 ||
                (code = float_params(op - 1, m, in)) < 0 ||
                (code = gs_function_evaluate(pfn, in, out)) < 0
                )
                DO_NOTHING;
            else {
                if (diff > 0)
                    push(diff);	/* can't fail */
                else if (diff < 0) {
                    pop(-diff);
                    op = osp;
                }
                code = make_floats(op + 1 - n, out, n);
            }
            if (in != params)
                ifree_object(in, "%execfunction(in)");
            return code;
        }
    }
}
예제 #15
0
static int
ref_param_read_typed(gs_param_list * plist, gs_param_name pkey,
		     gs_param_typed_value * pvalue)
{
    iparam_list *const iplist = (iparam_list *) plist;
    iparam_loc loc;
    ref elt;
    int code = ref_param_read(iplist, pkey, &loc, -1);

    if (code != 0)
	return code;
    switch (r_type(loc.pvalue)) {
	case t_array:
	case t_mixedarray:
	case t_shortarray:
	    iparam_check_read(loc);
	    if (r_size(loc.pvalue) <= 0) {
		/* 0-length array; can't get type info */
		pvalue->type = gs_param_type_array;
		pvalue->value.d.list = 0;
		pvalue->value.d.size = 0;
		return 0;
	    }
	    /*
	     * We have to guess at the array type.  First we guess based
	     * on the type of the first element of the array.  If that
	     * fails, we try again with more general types.
	     */
	    array_get(plist->memory, loc.pvalue, 0, &elt);
	    switch (r_type(&elt)) {
		case t_integer:
		    pvalue->type = gs_param_type_int_array;
		    code = ref_param_read_int_array(plist, pkey,
						    &pvalue->value.ia);
		    if (code != e_typecheck)
			return code;
		    /* This might be a float array.  Fall through. */
		    *loc.presult = 0;  /* reset error */
		case t_real:
		    pvalue->type = gs_param_type_float_array;
		    return ref_param_read_float_array(plist, pkey,
						      &pvalue->value.fa);
		case t_string:
		    pvalue->type = gs_param_type_string_array;
		    return ref_param_read_string_array(plist, pkey,
						       &pvalue->value.sa);
		case t_name:
		    pvalue->type = gs_param_type_name_array;
		    return ref_param_read_string_array(plist, pkey,
						       &pvalue->value.na);
		default:
		    break;
	    }
	    return gs_note_error(e_typecheck);
	case t_boolean:
	    pvalue->type = gs_param_type_bool;
	    pvalue->value.b = loc.pvalue->value.boolval;
	    return 0;
	case t_dictionary:
	    code = ref_param_begin_read_collection(plist, pkey,
			    &pvalue->value.d, gs_param_collection_dict_any);
	    if (code < 0)
		return code;
	    pvalue->type = gs_param_type_dict;

	    /* fixup new dict's type & int_keys field if contents have int keys */
	    {
		gs_param_enumerator_t enumr;
		gs_param_key_t key;
		ref_type keytype;

		param_init_enumerator(&enumr);
		if (!(*((iparam_list *) plist)->enumerate)
		    ((iparam_list *) pvalue->value.d.list, &enumr, &key, &keytype)
		    && keytype == t_integer) {
		    ((dict_param_list *) pvalue->value.d.list)->int_keys = 1;
		    pvalue->type = gs_param_type_dict_int_keys;
		}
	    }
	    return 0;
	case t_integer:
	    pvalue->type = gs_param_type_long;
	    pvalue->value.l = loc.pvalue->value.intval;
	    return 0;
	case t_name:
	    pvalue->type = gs_param_type_name;
	    return ref_param_read_string_value(plist->memory, &loc, &pvalue->value.n);
	case t_null:
	    pvalue->type = gs_param_type_null;
	    return 0;
	case t_real:
	    pvalue->value.f = loc.pvalue->value.realval;
	    pvalue->type = gs_param_type_float;
	    return 0;
	case t_string:
        case t_astruct:
	    pvalue->type = gs_param_type_string;
	    return ref_param_read_string_value(plist->memory, &loc, &pvalue->value.s);
	default:
	    break;
    }
    return gs_note_error(e_typecheck);
}
예제 #16
0
/* Returns exec_cont - a function, which must be called by caller after this function. */
static int
type1exec_bbox(i_ctx_t *i_ctx_p, gs_text_enum_t *penum, gs_type1exec_state * pcxs,
               gs_font * pfont, op_proc_t *exec_cont)
{
    os_ptr op = osp;
    gs_type1_state *const pcis = &pcxs->cis;
    gs_font_base *const pbfont = (gs_font_base *) pfont;
    op_proc_t cont = (pbfont->PaintType == 0 && penum->orig_font->PaintType == 0
                        ? bbox_finish_fill : bbox_finish_stroke);
    ref *pcdevproc;

    /*
     * We appear to have a valid bounding box.  If we don't have Metrics for
     * this character, start interpreting the CharString; do the
     * setcachedevice as soon as we know the (side bearing and) width.
     */
    if ((pcxs->present == metricsNone && !pcxs->use_FontBBox_as_Metrics2) ||
         (penum->orig_font->WMode && zchar_get_CDevProc(pbfont, &pcdevproc))) {
        /* Get the width from the CharString,
         * then set the cache device. */
        /* We pass here when WMode==1 and the font has CDevProc,
         * because we do need sbw as CDevProc's argument.
         * A more natural way would be not setting pcxs->use_FontBBox_as_Metrics2
         * when the font has CDevProc, except for missing sbw in the glyph.
         * We prefer to pass here because we've got examples
         * of Tyoe 1 fonts with empty glyphs, i.e. with no sbw,
         * so we don't want to assume that they'll never appear in a CID font.
         * In that case penum->FontBBox_as_Metrics2 will go here to zchar_set_cache. */
        ref cnref;
        ref other_subr;
        int code;

        /* Since an OtherSubr callout might change osp, */
        /* save the character name now. */
        ref_assign(&cnref, op - 1);
        code = type1_continue_dispatch(i_ctx_p, pcxs, op, &other_subr, 4);
        op = osp;		/* OtherSubrs might change it */
        switch (code) {
            default:		/* code < 0 or done, error */
                return ((code < 0 ? code :
                         gs_note_error(e_invalidfont)));
            case type1_result_callothersubr:	/* unknown OtherSubr */
                return type1_call_OtherSubr(i_ctx_p, pcxs,
                                            bbox_getsbw_continue,
                                            &other_subr);
            case type1_result_sbw:	/* [h]sbw, done */
                break;
        }
        type1_cis_get_metrics(pcis, pcxs->sbw);
        return zchar_set_cache(i_ctx_p, pbfont, &cnref,
                               NULL, pcxs->sbw + 2,
                               &pcxs->char_bbox,
                               cont, exec_cont, NULL);
    } else {
        /* We have the width and bounding box: */
        /* set up the cache device now. */
        return zchar_set_cache(i_ctx_p, pbfont, op - 1,
                               (pcxs->present == metricsSideBearingAndWidth
                                && !pcxs->use_FontBBox_as_Metrics2 ?
                                pcxs->sbw : NULL),
                               pcxs->sbw + 2,
                               &pcxs->char_bbox,
                               cont, exec_cont,
                               (pcxs->use_FontBBox_as_Metrics2 ? pcxs->sbw : NULL));
    }
}
예제 #17
0
/* Copy one parameter list to another, recursively if necessary. */
int
param_list_copy(gs_param_list *plto, gs_param_list *plfrom)
{
    gs_param_enumerator_t key_enum;
    gs_param_key_t key;
    /*
     * If plfrom and plto use different allocators, we must copy
     * aggregate values even if they are "persistent".
     */
    bool copy_persists = plto->memory == plfrom->memory;
    int code;

    param_init_enumerator(&key_enum);
    while ((code = param_get_next_key(plfrom, &key_enum, &key)) == 0) {
	char string_key[256];	/* big enough for any reasonable key */
	gs_param_typed_value value;
	gs_param_collection_type_t coll_type;
	gs_param_typed_value copy;

	if (key.size > sizeof(string_key) - 1) {
	    code = gs_note_error(gs_error_rangecheck);
	    break;
	}
	memcpy(string_key, key.data, key.size);
	string_key[key.size] = 0;
	if ((code = param_read_typed(plfrom, string_key, &value)) != 0) {
	    code = (code > 0 ? gs_note_error(gs_error_unknownerror) : code);
	    break;
	}
	gs_param_list_set_persistent_keys(plto, key.persistent);
	switch (value.type) {
	case gs_param_type_dict:
	    coll_type = gs_param_collection_dict_any;
	    goto cc;
	case gs_param_type_dict_int_keys:
	    coll_type = gs_param_collection_dict_int_keys;
	    goto cc;
	case gs_param_type_array:
	    coll_type = gs_param_collection_array;
	cc:
	    copy.value.d.size = value.value.d.size;
	    if ((code = param_begin_write_collection(plto, string_key,
						     &copy.value.d,
						     coll_type)) < 0 ||
		(code = param_list_copy(copy.value.d.list,
					value.value.d.list)) < 0 ||
		(code = param_end_write_collection(plto, string_key,
						   &copy.value.d)) < 0)
		break;
	    code = param_end_read_collection(plfrom, string_key,
					     &value.value.d);
	    break;
	case gs_param_type_string:
	    value.value.s.persistent &= copy_persists; goto ca;
	case gs_param_type_name:
	    value.value.n.persistent &= copy_persists; goto ca;
	case gs_param_type_int_array:
	    value.value.ia.persistent &= copy_persists; goto ca;
	case gs_param_type_float_array:
	    value.value.fa.persistent &= copy_persists; goto ca;
	case gs_param_type_string_array:
	    value.value.sa.persistent &= copy_persists;
	ca:
	default:
	    code = param_write_typed(plto, string_key, &value);
	}
	if (code < 0)
	    break;
    }
    return code;
}
예제 #18
0
/* Expand a buffer into a gs_param_list (including sub-dicts) */
int				/* ret -ve err, +ve # of chars read from buffer */
gs_param_list_unserialize(
                             gs_param_list * list,	/* root of list to expand to */
                                        /* list MUST BE IN WRITE MODE */
                             const byte * buf	/* source buffer */
)
{
    int code = 0;
    const byte *orig_buf = buf;

    do {
        gs_param_typed_value typed;
        gs_param_name key;
        unsigned key_sizeof;
        int value_top_sizeof;
        int value_base_sizeof;
        int temp_code;
        gs_param_type type;

        /* key length, 0 indicates end of data */
        key_sizeof = buf_get_word(&buf);
        if (key_sizeof == 0)	/* end of data */
            break;

        /* data type */
        type = (gs_param_type) buf_get_word(&buf);

        /* key */
        key = (gs_param_name) buf;
        buf += key_sizeof;

        /* Data values */
        value_top_sizeof = gs_param_type_sizes[type];
        value_base_sizeof = gs_param_type_base_sizes[type];
        typed.type = type;
        if (type != gs_param_type_dict && type != gs_param_type_dict_int_keys) {
            memcpy(&typed.value, buf, value_top_sizeof);
            buf += value_top_sizeof;
        }
        switch (type) {
            case gs_param_type_null:
            case gs_param_type_bool:
            case gs_param_type_int:
            case gs_param_type_long:
            case gs_param_type_float:
                break;

            case gs_param_type_string:
            case gs_param_type_name:
            case gs_param_type_int_array:
            case gs_param_type_float_array:
                ptr_align_to(&buf, value_base_sizeof);
                typed.value.s.data = buf;
                typed.value.s.persistent = false;
                buf += typed.value.s.size * value_base_sizeof;
                break;

            case gs_param_type_string_array:
            case gs_param_type_name_array:
                ptr_align_to(&buf, sizeof(void *));

                typed.value.sa.data = (const gs_param_string *)buf;
                typed.value.sa.persistent = false;
                buf += typed.value.s.size * value_base_sizeof;
                {
                    int str_count;
                    gs_param_string *sa;

                    for (str_count = typed.value.sa.size,
                         sa = (gs_param_string *) typed.value.sa.data;
                         str_count-- > 0; ++sa) {
                        sa->data = buf;
                        sa->persistent = false;
                        buf += sa->size;
                    }
                }
                break;

            case gs_param_type_dict:
            case gs_param_type_dict_int_keys:
                typed.value.d.size = buf_get_word(&buf);
                code = param_begin_write_dict
                    (list, key, &typed.value.d, type == gs_param_type_dict_int_keys);
                if (code < 0)
                    break;
                ptr_align_to(&buf, sizeof(void *));

                code = gs_param_list_unserialize(typed.value.d.list, buf);
                temp_code = param_end_write_dict(list, key, &typed.value.d);
                if (code >= 0) {
                    buf += code;
                    code = temp_code;
                }
                break;

            default:
                code = gs_note_error(gs_error_unknownerror);
                break;
        }
        if (code < 0)
            break;
        if (typed.type != gs_param_type_dict && typed.type != gs_param_type_dict_int_keys)
            code = param_write_typed(list, key, &typed);
    }
    while (code >= 0);

    return code >= 0 ? buf - orig_buf : code;
}
예제 #19
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;
}
예제 #20
0
/* Serialize the contents of a gs_param_list (including sub-dicts) */
int				/* ret -ve err, else # bytes needed to represent param list, whether */

/* or not it actually fit into buffer. List was successully */

/* serialized only if if this # is <= supplied buf size. */
gs_param_list_serialize(
                           gs_param_list * list,	/* root of list to serialize */
                                        /* list MUST BE IN READ MODE */
                           byte * buf,	/* destination buffer (can be 0) */
                           int buf_sizeof	/* # bytes available in buf (can be 0) */
)
{
    int code = 0;
    int temp_code;
    gs_param_enumerator_t key_enum;
    gs_param_key_t key;
    WriteBuffer write_buf;

    write_buf.buf = buf;
    write_buf.buf_end = buf + (buf ? buf_sizeof : 0);
    write_buf.total_sizeof = 0;
    param_init_enumerator(&key_enum);

    /* Each item is serialized as ("word" means compressed word):
     *  word: key sizeof + 1, or 0 if end of list/dict
     *  word: data type(gs_param_type_xxx)
     *  byte[]: key, including trailing \0
     *  (if simple type)
     *   byte[]: unpacked representation of data
     *  (if simple array or string)
     *   byte[]: unpacked mem image of gs_param_xxx_array structure
     *   pad: to array alignment
     *   byte[]: data associated with array contents
     *  (if string/name array)
     *   byte[]: unpacked mem image of gs_param_string_array structure
     *   pad: to void *
     *   { gs_param_string structure mem image;
     *     data associated with string;
     *   } for each string in array
     *  (if dict/dict_int_keys)
     *   word: # of entries in dict,
     *   pad: to void *
     *   dict entries follow immediately until end-of-dict
     *
     * NB that this format is designed to allow using an input buffer
     * as the direct source of data when expanding a gs_c_param_list
     */
    /* Enumerate all the keys; use keys to get their typed values */
    while ((code = param_get_next_key(list, &key_enum, &key)) == 0) {
        int value_top_sizeof;
        int value_base_sizeof;

        /* Get next datum & put its type & key to buffer */
        gs_param_typed_value value;
        char string_key[256];

        if (sizeof(string_key) < key.size + 1) {
            code = gs_note_error(gs_error_rangecheck);
            break;
        }
        memcpy(string_key, key.data, key.size);
        string_key[key.size] = 0;
        if ((code = param_read_typed(list, string_key, &value)) != 0) {
            code = code > 0 ? gs_note_error(gs_error_unknownerror) : code;
            break;
        }
        wb_put_word((unsigned)key.size + 1, &write_buf);
        wb_put_word((unsigned)value.type, &write_buf);
        wb_put_bytes((byte *) string_key, key.size + 1, &write_buf);

        /* Put value & its size to buffer */
        value_top_sizeof = gs_param_type_sizes[value.type];
        value_base_sizeof = gs_param_type_base_sizes[value.type];
        switch (value.type) {
            case gs_param_type_null:
            case gs_param_type_bool:
            case gs_param_type_int:
            case gs_param_type_long:
            case gs_param_type_float:
                wb_put_bytes((byte *) & value.value, value_top_sizeof, &write_buf);
                break;

            case gs_param_type_string:
            case gs_param_type_name:
            case gs_param_type_int_array:
            case gs_param_type_float_array:
                wb_put_bytes((byte *) & value.value, value_top_sizeof, &write_buf);
                wb_put_alignment(value_base_sizeof, &write_buf);
                value_base_sizeof *= value.value.s.size;
                wb_put_bytes(value.value.s.data, value_base_sizeof, &write_buf);
                break;

            case gs_param_type_string_array:
            case gs_param_type_name_array:
                value_base_sizeof *= value.value.sa.size;
                wb_put_bytes((const byte *)&value.value, value_top_sizeof, &write_buf);
                wb_put_alignment(sizeof(void *), &write_buf);

                wb_put_bytes((const byte *)value.value.sa.data, value_base_sizeof,
                          &write_buf);
                {
                    int str_count;
                    const gs_param_string *sa;

                    for (str_count = value.value.sa.size,
                         sa = value.value.sa.data; str_count-- > 0; ++sa)
                        wb_put_bytes(sa->data, sa->size, &write_buf);
                }
                break;

            case gs_param_type_dict:
            case gs_param_type_dict_int_keys:
                wb_put_word(value.value.d.size, &write_buf);
                wb_put_alignment(sizeof(void *), &write_buf);

                {
                    int bytes_written =
                    gs_param_list_serialize(value.value.d.list,
                                            write_buf.buf,
                     write_buf.buf ? write_buf.buf_end - write_buf.buf : 0);

                    temp_code = param_end_read_dict(list,
                                                    (const char *)key.data,
                                                    &value.value.d);
                    if (bytes_written < 0)
                        code = bytes_written;
                    else {
                        code = temp_code;
                        if (bytes_written)
                            wb_put_bytes(write_buf.buf, bytes_written, &write_buf);
                    }
                }
                break;

            default:
                code = gs_note_error(gs_error_unknownerror);
                break;
        }
        if (code < 0)
            break;
    }

    /* Write end marker, which is an (illegal) 0 key length */
    if (code >= 0) {
        wb_put_word(0, &write_buf);
        code = write_buf.total_sizeof;
    }
    return code;
}
예제 #21
0
/* Exported for use by background printing.                             */
gx_device *
setup_device_and_mem_for_thread(gs_memory_t *chunk_base_mem, gx_device *dev, bool bg_print, gsicc_link_cache_t **cachep)
{
    int i, code;
    char fmode[4];
    gs_memory_t *thread_mem;
    gx_device_clist *cldev = (gx_device_clist *)dev;
    gx_device_printer *pdev = (gx_device_printer *)dev;
    gx_device_clist_common *cdev = (gx_device_clist_common *)cldev;
    gx_device *ndev;
    gx_device_clist *ncldev;
    gx_device_clist_common *ncdev;
    gx_device_printer *npdev;
    gx_device *protodev;
    gs_c_param_list paramlist;
    gs_devn_params *pclist_devn_params;

    /* Every thread will have a 'chunk allocator' to reduce the interaction
     * with the 'base' allocator which has 'mutex' (locking) protection.
     * This improves performance of the threads.
     */
    if ((code = gs_memory_chunk_wrap(&(thread_mem), chunk_base_mem )) < 0) {
        emprintf1(dev->memory, "chunk_wrap returned error code: %d\n", code);
        return NULL;
    }
    /* Find the prototype for this device (needed so we can copy from it) */
    for (i=0; (protodev = (gx_device *)gs_getdevice(i)) != NULL; i++)
        if (strcmp(protodev->dname, dev->dname) == 0)
            break;

    /* Clone the device from the prototype device */
    if (protodev == NULL ||
        (code = gs_copydevice((gx_device **) &ndev, protodev, thread_mem)) < 0) {
        gs_memory_chunk_release(thread_mem);
        return NULL;
    }
    ncldev = (gx_device_clist *)ndev;
    ncdev = (gx_device_clist_common *)ndev;
    npdev = (gx_device_printer *)ndev;
    gx_device_fill_in_procs(ndev);
    ((gx_device_printer *)ncdev)->buffer_memory =
        ncdev->memory =
            ncdev->bandlist_memory =
               thread_mem;
    ndev->PageCount = dev->PageCount;       /* copy to prevent mismatch error */
    npdev->file = pdev->file;               /* For background printing when doing N copies with %d */
    strcpy((npdev->fname), (pdev->fname));
    ndev->color_info = dev->color_info;     /* copy before putdeviceparams */
    ndev->pad = dev->pad;
    ndev->log2_align_mod = dev->log2_align_mod;
    ndev->is_planar = dev->is_planar;
#if CMM_THREAD_SAFE
        ndev->icc_struct = dev->icc_struct;  /* Set before put params */
        rc_increment(ndev->icc_struct);
#endif
    /* get the current device parameters to put into the cloned device */
    gs_c_param_list_write(&paramlist, dev->memory);
    if ((code = gs_getdeviceparams(dev, (gs_param_list *)&paramlist)) < 0) {
        emprintf1(dev->memory,
                  "Error getting device params, code=%d. Rendering threads not started.\n",
                  code);
        goto out_cleanup;
    }
    gs_c_param_list_read(&paramlist);
    if ((code = gs_putdeviceparams(ndev, (gs_param_list *)&paramlist)) < 0)
        goto out_cleanup;
    gs_c_param_list_release(&paramlist);

    /* In the case of a separation device, we need to make sure we get the
       devn params copied over */
    pclist_devn_params = dev_proc(dev, ret_devn_params)(dev);
    if (pclist_devn_params != NULL) {
        code = devn_copy_params(dev, ndev);
        if (code < 0) {
#ifdef DEBUG /* suppress a warning on a release build */
            gs_note_error(gs_error_VMerror);
#endif
            goto out_cleanup;
        }
    }
    /* Also make sure supports_devn is set correctly */
    ndev->icc_struct->supports_devn = cdev->icc_struct->supports_devn;
    ncdev->page_uses_transparency = cdev->page_uses_transparency;
    if_debug3m(gs_debug_flag_icc, cdev->memory,
               "[icc] MT clist device = 0x%p profile = 0x%p handle = 0x%p\n",
               ncdev,
               ncdev->icc_struct->device_profile[0],
               ncdev->icc_struct->device_profile[0]->profile_handle);
    /* If the device is_planar, then set the flag in the new_device and the procs */
    if ((ncdev->is_planar = cdev->is_planar))
        gdev_prn_set_procs_planar(ndev);

    /* gdev_prn_allocate_memory sets the clist for writing, creating new files.
     * We need  to unlink those files and open the main thread's files, then
     * reset the clist state for reading/rendering
     */
    if ((code = gdev_prn_allocate_memory(ndev, NULL, ndev->width, ndev->height)) < 0)
        goto out_cleanup;

    /* close and unlink the temp files just created */
    ncdev->page_info.io_procs->fclose(ncdev->page_info.cfile, ncdev->page_info.cfname, true);
    ncdev->page_info.io_procs->fclose(ncdev->page_info.bfile, ncdev->page_info.bfname, true);
    ncdev->page_info.cfile = ncdev->page_info.bfile = NULL;

    /* open the main thread's files for this thread */
    strcpy(fmode, "r");                 /* read access for threads */
    strncat(fmode, gp_fmode_binary_suffix, 1);
    if ((code=cdev->page_info.io_procs->fopen(cdev->page_info.cfname, fmode, &ncdev->page_info.cfile,
                        thread_mem, thread_mem, true)) < 0 ||
         (code=cdev->page_info.io_procs->fopen(cdev->page_info.bfname, fmode, &ncdev->page_info.bfile,
                        thread_mem, thread_mem, false)) < 0)
        goto out_cleanup;

    strcpy((ncdev->page_info.cfname), (cdev->page_info.cfname));
    strcpy((ncdev->page_info.bfname), (cdev->page_info.bfname));
    clist_render_init(ncldev);      /* Initialize clist device for reading */
    ncdev->page_info.bfile_end_pos = cdev->page_info.bfile_end_pos;

    /* The threads are maintained until clist_finish_page.  At which
       point, the threads are torn down, the master clist reader device
       is changed to writer, and the icc_table and the icc_cache_cl freed */
#if CMM_THREAD_SAFE
    /* safe to share the link cache */
    ncdev->icc_cache_cl = cdev->icc_cache_cl;
    rc_increment(cdev->icc_cache_cl, "setup_render_thread");
#else
    /* each thread needs its own link cache */
    if (cachep != NULL) {
        if (*cachep == NULL) {
            /* We don't have one cached that we can reuse, so make one. */
            if ((*cachep = gsicc_cache_new(thread_mem->thread_safe_memory)) == NULL)
                goto out_cleanup;
        }
        rc_increment(*cachep);
        ncdev->icc_cache_cl = *cachep;
    } else if ((ncdev->icc_cache_cl = gsicc_cache_new(thread_mem)) == NULL)
        goto out_cleanup;
#endif
    if (bg_print) {
        gx_device_clist_reader *ncrdev = (gx_device_clist_reader *)ncdev;

        if (cdev->icc_table != NULL) {
            /* This is a background printing thread, so it cannot share the icc_table  */
            /* since this probably was created with a GC'ed allocator and the bg_print */
            /* thread can't deal with the relocation. Free the cdev->icc_table and get */
            /* a new one from the clist.                                               */
            clist_free_icc_table(cdev->icc_table, cdev->memory);
            cdev->icc_table = NULL;
            if ((code = clist_read_icctable((gx_device_clist_reader *)ncdev)) < 0)
                goto out_cleanup;
        }
        /* Similarly for the color_usage_array, when the foreground device switches to */
        /* writer mode, the foreground's array will be freed.                          */
        if ((code = clist_read_color_usage_array(ncrdev)) < 0)
            goto out_cleanup;
    } else {
    /* Use the same profile table and color usage array in each thread */
        ncdev->icc_table = cdev->icc_table;		/* OK for multiple rendering threads */
        ((gx_device_clist_reader *)ncdev)->color_usage_array =
                ((gx_device_clist_reader *)cdev)->color_usage_array;
    }
    /* Needed for case when the target has cielab profile and pdf14 device
       has a RGB profile stored in the profile list of the clist */
    ncdev->trans_dev_icc_hash = cdev->trans_dev_icc_hash;

    /* success */
    return ndev;

out_cleanup:
    /* Close the file handles, but don't delete (unlink) the files */
    if (ncdev->page_info.bfile != NULL)
        ncdev->page_info.io_procs->fclose(ncdev->page_info.bfile, ncdev->page_info.bfname, false);
    if (ncdev->page_info.cfile != NULL)
        ncdev->page_info.io_procs->fclose(ncdev->page_info.cfile, ncdev->page_info.cfname, false);
    ncdev->do_not_open_or_close_bandfiles = true; /* we already closed the files */

    if (ndev != NULL) {
        gdev_prn_free_memory(ndev);
        gs_free_object(thread_mem, ndev, "setup_device_and_mem_for_thread");
    }
    gs_memory_chunk_release(thread_mem);
    return NULL;
}
예제 #22
0
int
clist_unlink(const char *fname)
{	return (unlink(fname) != 0 ? gs_note_error(gs_error_ioerror) : 0);
}
예제 #23
0
static int
zsetcolorscreen(i_ctx_t *i_ctx_p)
{
    os_ptr op = osp;
    gs_colorscreen_halftone cscreen;
    ref sprocs[4];
    gs_halftone *pht;
    gx_device_halftone *pdht;
    int i;
    int code = 0;
    int space = 0;
    gs_memory_t *mem;

    for (i = 0; i < 4; i++) {
        os_ptr op1 = op - 9 + i * 3;
        int code = zscreen_params(op1, &cscreen.screens.indexed[i]);

        if (code < 0)
            return code;
        cscreen.screens.indexed[i].spot_function = spot_dummy;
        sprocs[i] = *op1;
        space = max(space, r_space_index(op1));
    }
    mem = (gs_memory_t *)idmemory->spaces_indexed[space];
    check_estack(8);		/* for sampling screens */
    rc_alloc_struct_0(pht, gs_halftone, &st_halftone,
                      mem, pht = 0, "setcolorscreen(halftone)");
    rc_alloc_struct_0(pdht, gx_device_halftone, &st_device_halftone,
                      mem, pdht = 0, "setcolorscreen(device halftone)");
    if (pht == 0 || pdht == 0)
        code = gs_note_error(e_VMerror);
    else {
        pht->type = ht_type_colorscreen;
        pht->params.colorscreen = cscreen;
        code = gs_sethalftone_prepare(igs, pht, pdht);
    }
    if (code >= 0) {		/* Schedule the sampling of the screens. */
        es_ptr esp0 = esp;	/* for backing out */

        esp += 8;
        make_mark_estack(esp - 7, es_other, setcolorscreen_cleanup);
        memcpy(esp - 6, sprocs, sizeof(ref) * 4);	/* procs */
        make_istruct(esp - 2, 0, pht);
        make_istruct(esp - 1, 0, pdht);
        make_op_estack(esp, setcolorscreen_finish);
        for (i = 0; i < 4; i++) {
            /* Shuffle the indices to correspond to */
            /* the component order. */
            code = zscreen_enum_init(i_ctx_p,
                                     &pdht->components[(i + 1) & 3].corder,
                                     &pht->params.colorscreen.screens.indexed[i],
                                     &sprocs[i], 0, 0, space);
            if (code < 0) {
                esp = esp0;
                break;
            }
        }
    }
    if (code < 0) {
        gs_free_object(mem, pdht, "setcolorscreen(device halftone)");
        gs_free_object(mem, pht, "setcolorscreen(halftone)");
        return code;
    }
    pop(12);
    return o_push_estack;
}
예제 #24
0
/* This routine is used for all formats. */
static int
png_print_page(gx_device_printer * pdev, FILE * file)
{
    gs_memory_t *mem = pdev->memory;
    int raster = gdev_prn_raster(pdev);

    /* PNG structures */
    byte *row = gs_alloc_bytes(mem, raster, "png raster buffer");
    png_struct *png_ptr =
    png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    png_info *info_ptr =
    png_create_info_struct(png_ptr);
    int height = pdev->height;
    int depth = pdev->color_info.depth;
    int y;
    int code;			/* return code */
    char software_key[80];
    char software_text[256];
    png_text text_png;

    if (row == 0 || png_ptr == 0 || info_ptr == 0) {
	code = gs_note_error(gs_error_VMerror);
	goto done;
    }
    /* set error handling */
    if (setjmp(png_ptr->jmpbuf)) {
	/* If we get here, we had a problem reading the file */
	code = gs_note_error(gs_error_VMerror);
	goto done;
    }
    code = 0;			/* for normal path */
    /* set up the output control */
    png_init_io(png_ptr, file);

    /* set the file information here */
    info_ptr->width = pdev->width;
    info_ptr->height = pdev->height;
    /* resolution is in pixels per meter vs. dpi */
    info_ptr->x_pixels_per_unit =
	(png_uint_32) (pdev->HWResolution[0] * (100.0 / 2.54));
    info_ptr->y_pixels_per_unit =
	(png_uint_32) (pdev->HWResolution[1] * (100.0 / 2.54));
    info_ptr->phys_unit_type = PNG_RESOLUTION_METER;
    info_ptr->valid |= PNG_INFO_pHYs;
    switch (depth) {
	case 32:
	    info_ptr->bit_depth = 8;
	    info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
	    png_set_invert_alpha(png_ptr);
	    {   gx_device_pngalpha *ppdev = (gx_device_pngalpha *)pdev;
		png_color_16 background;
		background.index = 0;
		background.red =   (ppdev->background >> 16) & 0xff;
		background.green = (ppdev->background >> 8)  & 0xff;
		background.blue =  (ppdev->background)       & 0xff;
		background.gray = 0;
		png_set_bKGD(png_ptr, info_ptr, &background);
	    }
	    break;
	case 48:
	    info_ptr->bit_depth = 16;
	    info_ptr->color_type = PNG_COLOR_TYPE_RGB;
#if defined(ARCH_IS_BIG_ENDIAN) && (!ARCH_IS_BIG_ENDIAN) 
	    png_set_swap(png_ptr);
#endif
	    break;
	case 24:
	    info_ptr->bit_depth = 8;
	    info_ptr->color_type = PNG_COLOR_TYPE_RGB;
	    break;
	case 8:
	    info_ptr->bit_depth = 8;
	    if (gx_device_has_color(pdev))
		info_ptr->color_type = PNG_COLOR_TYPE_PALETTE;
	    else
		info_ptr->color_type = PNG_COLOR_TYPE_GRAY;
	    break;
	case 4:
	    info_ptr->bit_depth = 4;
	    info_ptr->color_type = PNG_COLOR_TYPE_PALETTE;
	    break;
	case 1:
	    info_ptr->bit_depth = 1;
	    info_ptr->color_type = PNG_COLOR_TYPE_GRAY;
	    /* invert monocrome pixels */
	    png_set_invert_mono(png_ptr);
	    break;
    }

    /* set the palette if there is one */
    if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) {
	int i;
	int num_colors = 1 << depth;
	gx_color_value rgb[3];

	info_ptr->palette =
	    (void *)gs_alloc_bytes(mem, 256 * sizeof(png_color),
				   "png palette");
	if (info_ptr->palette == 0) {
	    code = gs_note_error(gs_error_VMerror);
	    goto done;
	}
	info_ptr->num_palette = num_colors;
	info_ptr->valid |= PNG_INFO_PLTE;
	for (i = 0; i < num_colors; i++) {
	    (*dev_proc(pdev, map_color_rgb)) ((gx_device *) pdev,
					      (gx_color_index) i, rgb);
	    info_ptr->palette[i].red = gx_color_value_to_byte(rgb[0]);
	    info_ptr->palette[i].green = gx_color_value_to_byte(rgb[1]);
	    info_ptr->palette[i].blue = gx_color_value_to_byte(rgb[2]);
	}
    }
    /* add comment */
    strncpy(software_key, "Software", sizeof(software_key));
    sprintf(software_text, "%s %d.%02d", gs_product,
	    (int)(gs_revision / 100), (int)(gs_revision % 100));
    text_png.compression = -1;	/* uncompressed */
    text_png.key = software_key;
    text_png.text = software_text;
    text_png.text_length = strlen(software_text);
    info_ptr->text = &text_png;
    info_ptr->num_text = 1;

    /* write the file information */
    png_write_info(png_ptr, info_ptr);

    /* don't write the comments twice */
    info_ptr->num_text = 0;
    info_ptr->text = NULL;

    /* Write the contents of the image. */
    for (y = 0; y < height; y++) {
	gdev_prn_copy_scan_lines(pdev, y, row, raster);
	png_write_rows(png_ptr, &row, 1);
    }

    /* write the rest of the file */
    png_write_end(png_ptr, info_ptr);

    /* if you alloced the palette, free it here */
    gs_free_object(mem, info_ptr->palette, "png palette");

  done:
    /* free the structures */
    png_destroy_write_struct(&png_ptr, &info_ptr);
    gs_free_object(mem, row, "png raster buffer");

    return code;
}
예제 #25
0
/*
 * Open this printer device in ASYNC (overlapped) mode.
 * This routine must always called by the concrete device's xx_open routine
 * in lieu of gdev_prn_open.
 */
int
gdev_prn_async_write_open(gx_device_printer * pwdev, int max_raster,
                          int min_band_height, int max_src_image_row)
{
    gx_device *const pdev = (gx_device *) pwdev;
    int code;
    bool writer_is_open = false;
    gx_device_clist_writer *const pcwdev =
        &((gx_device_clist *) pwdev)->writer;
    gx_device_clist_reader *pcrdev = 0;
    gx_device_printer *prdev = 0;
    gs_memory_t *render_memory = 0;	/* renderer's mem allocator */

    pwdev->page_queue = 0;
    pwdev->bandlist_memory = 0;
    pwdev->async_renderer = 0;

    /* allocate & init render memory */
    /* The big memory consumers are: */
    /* - the buffer used to read images from the command list */
    /* - buffer used by gx_real_default_strip_copy_rop() */
    /* - line pointer tables for memory devices used in plane extraction */
    /* - the halftone cache */
    /* - the band rendering buffer */
    /* The * 2's in the next statement are a ****** HACK ****** to deal with */
    /* sandbars in the memory manager. */
    if ((code = alloc_render_memory(&render_memory,
            pwdev->memory->non_gc_memory, RendererAllocationOverheadBytes + max_raster
                                    /* the first * 2 is not a hack */
                   + (max_raster + sizeof(void *) * 2) * min_band_height
                   + max_src_image_row + gx_ht_cache_default_bits_size() * 2)) < 0)
             goto open_err;

    /* Alloc & init bandlist allocators */
    /* Bandlist mem is threadsafe & common to rdr/wtr, so it's used */
    /* for page queue & cmd list buffers. */
    if ((code = alloc_bandlist_memory
         (&pwdev->bandlist_memory, pwdev->memory->non_gc_memory)) < 0)
        goto open_err;

    /* Dictate banding parameters for both renderer & writer */
    /* Protect from user change, since user changing these won't be */
    /* detected, ergo the necessary close/reallocate/open wouldn't happen. */
    pwdev->space_params.banding_type = BandingAlways;
    pwdev->space_params.params_are_read_only = true;

    /* Make a copy of device for use as rendering device b4 opening writer */
    code = gs_copydevice((gx_device **) & prdev, pdev, render_memory);
    pcrdev = &((gx_device_clist *) prdev)->reader;
    if (code < 0)
        goto open_err;

    /* -------------- Open cmd list WRITER instance of device ------- */
    /* --------------------------------------------------------------- */
    /* This is wrong, because it causes the same thing in the renderer */
    pwdev->OpenOutputFile = 0;	/* Don't open output file in writer */

    /* Hack: set this vector to tell gdev_prn_open to allocate for async rendering */
    pwdev->free_up_bandlist_memory = &gdev_prn_async_write_free_up_bandlist_memory;

    /* prevent clist writer from queuing path graphics & force it to split images */
    pwdev->clist_disable_mask |= clist_disable_fill_path |
        clist_disable_stroke_path | clist_disable_complex_clip |
        clist_disable_nonrect_hl_image | clist_disable_pass_thru_params;

    if ((code = gdev_prn_open(pdev)) >= 0) {
        writer_is_open = true;

        /* set up constant async-specific fields in device */
        reinit_printer_into_printera(pwdev);

        /* keep ptr to renderer device */
        pwdev->async_renderer = prdev;

        /* Allocate the page queue, then initialize it */
        /* Use bandlist memory since it's shared between rdr & wtr */
        if ((pwdev->page_queue = gx_page_queue_alloc(pwdev->bandlist_memory)) == 0)
            code = gs_note_error(gs_error_VMerror);
        else
            /* Allocate from clist allocator since it is thread-safe */
            code = gx_page_queue_init(pwdev->page_queue, pwdev->bandlist_memory);
    }
    /* ------------ Open cmd list RENDERER instance of device ------- */
    /* --------------------------------------------------------------- */
    if (code >= 0) {
        gx_semaphore_t *open_semaphore;

        /* Force writer's actual band params into reader's requested params */
        prdev->space_params.band = pcwdev->page_info.band_params;

        /* copydevice has already set up prdev->memory = render_memory */
        /* prdev->bandlist_memory = pwdev->bandlist_memory; */
        prdev->buffer_memory = prdev->memory;

        /* enable renderer to accept changes to params computed by writer */
        prdev->space_params.params_are_read_only = false;

        /* page queue is common to both devices */
        prdev->page_queue = pwdev->page_queue;

        /* Start renderer thread & wait for its successful open of device */
        if (!(open_semaphore = gx_semaphore_alloc(prdev->memory)))
            code = gs_note_error(gs_error_VMerror);
        else {
            gdev_prn_start_render_params thread_params;

            thread_params.writer_device = pwdev;
            thread_params.open_semaphore = open_semaphore;
            thread_params.open_code = 0;
            code = (*pwdev->printer_procs.start_render_thread)
                (&thread_params);
            if (code >= 0)
                gx_semaphore_wait(open_semaphore);
            code = thread_params.open_code;
            gx_semaphore_free(open_semaphore);
        }
    }
    /* ----- Set the recovery procedure for the mem allocator ----- */
    if (code >= 0) {
        gs_memory_retrying_set_recover(
                (gs_memory_retrying_t *)pwdev->memory->non_gc_memory,
                prna_mem_recover,
                (void *)pcwdev
            );
    }
    /* --------------------- Wrap up --------------------------------- */
    /* --------------------------------------------------------------- */
    if (code < 0) {
open_err:
        /* error mop-up */
        if (render_memory && !prdev)
            free_render_memory(render_memory);

        gdev_prn_dealloc(pwdev);
        if (writer_is_open) {
            gdev_prn_close(pdev);
            pwdev->free_up_bandlist_memory = 0;
        }
    }
    return code;
}
예제 #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));
}
예제 #27
0
파일: zchar.c 프로젝트: ststeiger/ghostsvg
/*
 * Note that op_show_continue_dispatch sets osp = op explicitly iff the
 * dispatch succeeds.  This is so that the show operators don't pop anything
 * from the o-stack if they don't succeed.  Note also that if it returns an
 * error, it has freed the enumerator.
 */
int
op_show_continue_dispatch(i_ctx_t *i_ctx_p, int npop, int code)
{
    os_ptr op = osp - npop;
    gs_text_enum_t *penum = senum;

    switch (code) {
	case 0: {		/* all done */
	    os_ptr save_osp = osp;

	    osp = op;
	    code = (*real_opproc(&seproc)) (i_ctx_p);
	    op_show_free(i_ctx_p, code);
	    if (code < 0) {
		osp = save_osp;
		return code;
	    }
	    return o_pop_estack;
	}
	case TEXT_PROCESS_INTERVENE: {
	    ref *pslot = &sslot; /* only used for kshow */

	    push(2);
	    make_int(op - 1, gs_text_current_char(penum)); /* previous char */
	    make_int(op, gs_text_next_char(penum));
	    push_op_estack(op_show_continue);	/* continue after kerning */
	    *++esp = *pslot;	/* kerning procedure */
	    return o_push_estack;
	}
	case TEXT_PROCESS_RENDER: {
	    gs_font *pfont = gs_currentfont(igs);
	    font_data *pfdata = pfont_data(pfont);
	    gs_char chr = gs_text_current_char(penum);
	    gs_glyph glyph = gs_text_current_glyph(penum);

	    push(2);
	    op[-1] = pfdata->dict;	/* push the font */
	    /*
	     * For Type 1 and Type 4 fonts, prefer BuildChar to BuildGlyph
	     * if there is no glyph, or if there is both a character and a
	     * glyph and the glyph is the one that corresponds to the
	     * character in the Encoding, so that PostScript procedures
	     * appearing in the CharStrings dictionary will receive the
	     * character code rather than the character name; for Type 3
	     * fonts, prefer BuildGlyph to BuildChar.  For other font types
	     * (such as CID fonts), only BuildGlyph will be present.
	     */
	    if (pfont->FontType == ft_user_defined) {
		/* Type 3 font, prefer BuildGlyph. */
		if (level2_enabled &&
		    !r_has_type(&pfdata->BuildGlyph, t_null) &&
		    glyph != gs_no_glyph
		    ) {
		    glyph_ref(imemory, glyph, op);
		    esp[2] = pfdata->BuildGlyph;
		} else if (r_has_type(&pfdata->BuildChar, t_null))
		    goto err;
		else if (chr == gs_no_char) {
		    /* glyphshow, reverse map the character */
		    /* through the Encoding */
		    ref gref;
		    const ref *pencoding = &pfdata->Encoding;

		    glyph_ref(imemory, glyph, &gref);
		    if (!map_glyph_to_char(imemory, &gref, pencoding,
					   (ref *) op)
			) {	/* Not found, try .notdef */
		        name_enter_string(imemory, ".notdef", &gref);
			if (!map_glyph_to_char(imemory, &gref,
					       pencoding,
					       (ref *) op)
			    )
			    goto err;
		    }
		    esp[2] = pfdata->BuildChar;
		} else {
		    make_int(op, chr & 0xff);
		    esp[2] = pfdata->BuildChar;
		}
	    } else {
		/*
		 * For a Type 1 or Type 4 font, prefer BuildChar or
		 * BuildGlyph as described above: we know that both
		 * BuildChar and BuildGlyph are present.  For other font
		 * types, only BuildGlyph is available.
		 */
		ref eref, gref;

		if (chr != gs_no_char &&
		    !r_has_type(&pfdata->BuildChar, t_null) &&
		    (glyph == gs_no_glyph ||
		     (!r_has_type(&pfdata->Encoding, t_null) &&
		       array_get(imemory, &pfdata->Encoding, (long)(chr & 0xff), &eref) >= 0 &&
		      (glyph_ref(imemory, glyph, &gref), obj_eq(imemory, &gref, &eref))))
		    ) {
		    make_int(op, chr & 0xff);
		    esp[2] = pfdata->BuildChar;
		} else {
		    /* We might not have a glyph: substitute 0. **HACK** */
		    if (glyph == gs_no_glyph)
			make_int(op, 0);
		    else
		        glyph_ref(imemory, glyph, op);
		    esp[2] = pfdata->BuildGlyph;
		}
	    }
	    /* Save the stack depths in case we bail out. */
	    sodepth.value.intval = ref_stack_count(&o_stack) - 2;
	    sddepth.value.intval = ref_stack_count(&d_stack);
	    push_op_estack(op_show_continue);
	    ++esp;		/* skip BuildChar or BuildGlyph proc */
	    return o_push_estack;
	}
	case TEXT_PROCESS_CDEVPROC:
	    {   gs_font *pfont = penum->current_font;
		ref cnref;
		op_proc_t cont = op_show_continue, exec_cont = 0;
		gs_glyph glyph = penum->returned.current_glyph;
		int code;
    
		pop(npop);
		op = osp;
		glyph_ref(imemory, glyph, &cnref);
		if (pfont->FontType == ft_CID_TrueType) {
		    gs_font_type42 *pfont42 = (gs_font_type42 *)pfont;
		    uint glyph_index = pfont42->data.get_glyph_index(pfont42, glyph);

		    code = zchar42_set_cache(i_ctx_p, (gs_font_base *)pfont42, 
				    &cnref, glyph_index, cont, &exec_cont);
		} else if (pfont->FontType == ft_CID_encrypted)
		    code = z1_set_cache(i_ctx_p, (gs_font_base *)pfont, 
				    &cnref, glyph, cont, &exec_cont);
		else
		    return_error(e_unregistered); /* Unimplemented. */
		if (exec_cont != 0)
		    return_error(e_unregistered); /* Must not happen. */
		return code;
	    }
	default:		/* error */
err:
	    if (code >= 0)
		code = gs_note_error(e_invalidfont);
	    return op_show_free(i_ctx_p, code);
    }
}
예제 #28
0
파일: zht2.c 프로젝트: hackqiang/gs
static int
zsethalftone5(i_ctx_t *i_ctx_p)
{
    os_ptr op = osp;
    uint count;
    gs_halftone_component *phtc = 0;
    gs_halftone_component *pc;
    int code = 0;
    int j;
    bool have_default;
    gs_halftone *pht = 0;
    gx_device_halftone *pdht = 0;
    ref sprocs[GS_CLIENT_COLOR_MAX_COMPONENTS + 1];
    ref tprocs[GS_CLIENT_COLOR_MAX_COMPONENTS + 1];
    gs_memory_t *mem;
    uint edepth = ref_stack_count(&e_stack);
    int npop = 2;
    int dict_enum = dict_first(op);
    ref rvalue[2];
    int cname, colorant_number;
    byte * pname;
    uint name_size;
    int halftonetype, type = 0;
    gs_state *pgs = igs;
    int space_index = r_space_index(op - 1);

    mem = (gs_memory_t *) idmemory->spaces_indexed[space_index];

    check_type(*op, t_dictionary);
    check_dict_read(*op);
    check_type(op[-1], t_dictionary);
    check_dict_read(op[-1]);

    /*
     * We think that Type 2 and Type 4 halftones, like
     * screens set by setcolorscreen, adapt automatically to
     * the device color space, so we need to mark them
     * with a different internal halftone type.
     */
    code = dict_int_param(op - 1, "HalftoneType", 1, 100, 0, &type);
    if (code < 0)
          return code;
    halftonetype = (type == 2 || type == 4)
                        ? ht_type_multiple_colorscreen
                        : ht_type_multiple;

    /* Count how many components that we will actually use. */

    have_default = false;
    for (count = 0; ;) {

        /* Move to next element in the dictionary */
        if ((dict_enum = dict_next(op, dict_enum, rvalue)) == -1)
            break;
        /*
         * Verify that we have a valid component.  We may have a
         * /HalfToneType entry.
         */
        if (!r_has_type(&rvalue[0], t_name))
            continue;
        if (!r_has_type(&rvalue[1], t_dictionary))
            continue;

        /* Get the name of the component  verify that we will use it. */
        cname = name_index(mem, &rvalue[0]);
        code = gs_get_colorname_string(mem, cname, &pname, &name_size);
        if (code < 0)
            break;
        colorant_number = gs_cname_to_colorant_number(pgs, pname, name_size,
                                                halftonetype);
        if (colorant_number < 0)
            continue;
        else if (colorant_number == GX_DEVICE_COLOR_MAX_COMPONENTS) {
            /* If here then we have the "Default" component */
            if (have_default)
                return_error(e_rangecheck);
            have_default = true;
        }

        count++;
        /*
         * Check to see if we have already reached the legal number of
         * components.
         */
        if (count > GS_CLIENT_COLOR_MAX_COMPONENTS + 1) {
            code = gs_note_error(e_rangecheck);
            break;
        }
    }
    if (count == 0 || (halftonetype == ht_type_multiple && ! have_default))
        code = gs_note_error(e_rangecheck);

    if (code >= 0) {
        check_estack(5);		/* for sampling Type 1 screens */
        refset_null(sprocs, count);
        refset_null(tprocs, count);
        rc_alloc_struct_0(pht, gs_halftone, &st_halftone,
                          imemory, pht = 0, ".sethalftone5");
        phtc = gs_alloc_struct_array(mem, count, gs_halftone_component,
                                     &st_ht_component_element,
                                     ".sethalftone5");
        rc_alloc_struct_0(pdht, gx_device_halftone, &st_device_halftone,
                          imemory, pdht = 0, ".sethalftone5");
        if (pht == 0 || phtc == 0 || pdht == 0) {
            j = 0; /* Quiet the compiler:
                      gs_note_error isn't necessarily identity,
                      so j could be left ununitialized. */
            code = gs_note_error(e_VMerror);
        }
    }
    if (code >= 0) {
        dict_enum = dict_first(op);
        for (j = 0, pc = phtc; ;) {
            int type;

            /* Move to next element in the dictionary */
            if ((dict_enum = dict_next(op, dict_enum, rvalue)) == -1)
                break;
            /*
             * Verify that we have a valid component.  We may have a
             * /HalfToneType entry.
             */
            if (!r_has_type(&rvalue[0], t_name))
                continue;
            if (!r_has_type(&rvalue[1], t_dictionary))
                continue;

            /* Get the name of the component */
            cname = name_index(mem, &rvalue[0]);
            code = gs_get_colorname_string(mem, cname, &pname, &name_size);
            if (code < 0)
                break;
            colorant_number = gs_cname_to_colorant_number(pgs, pname, name_size,
                                                halftonetype);
            if (colorant_number < 0)
                continue;		/* Do not use this component */
            pc->cname = cname;
            pc->comp_number = colorant_number;

            /* Now process the component dictionary */
            check_dict_read(rvalue[1]);
            if (dict_int_param(&rvalue[1], "HalftoneType", 1, 7, 0, &type) < 0) {
                code = gs_note_error(e_typecheck);
                break;
            }
            switch (type) {
                default:
                    code = gs_note_error(e_rangecheck);
                    break;
                case 1:
                    code = dict_spot_params(&rvalue[1], &pc->params.spot,
                                                sprocs + j, tprocs + j, mem);
                    pc->params.spot.screen.spot_function = spot1_dummy;
                    pc->type = ht_type_spot;
                    break;
                case 3:
                    code = dict_threshold_params(&rvalue[1], &pc->params.threshold,
                                                        tprocs + j);
                    pc->type = ht_type_threshold;
                    break;
                case 7:
                    code = dict_threshold2_params(&rvalue[1], &pc->params.threshold2,
                                                        tprocs + j, imemory);
                    pc->type = ht_type_threshold2;
                    break;
            }
            if (code < 0)
                break;
            pc++;
            j++;
        }
    }
    if (code >= 0) {
        pht->type = halftonetype;
        pht->params.multiple.components = phtc;
        pht->params.multiple.num_comp = j;
        pht->params.multiple.get_colorname_string = gs_get_colorname_string;
        code = gs_sethalftone_prepare(igs, pht, pdht);
    }
    if (code >= 0) {
        /*
         * Put the actual frequency and angle in the spot function component dictionaries.
         */
        dict_enum = dict_first(op);
        for (pc = phtc; ; ) {
            /* Move to next element in the dictionary */
            if ((dict_enum = dict_next(op, dict_enum, rvalue)) == -1)
                break;

            /* Verify that we have a valid component */
            if (!r_has_type(&rvalue[0], t_name))
                continue;
            if (!r_has_type(&rvalue[1], t_dictionary))
                continue;

            /* Get the name of the component and verify that we will use it. */
            cname = name_index(mem, &rvalue[0]);
            code = gs_get_colorname_string(mem, cname, &pname, &name_size);
            if (code < 0)
                break;
            colorant_number = gs_cname_to_colorant_number(pgs, pname, name_size,
                                                halftonetype);
            if (colorant_number < 0)
                continue;

            if (pc->type == ht_type_spot) {
                code = dict_spot_results(i_ctx_p, &rvalue[1], &pc->params.spot);
                if (code < 0)
                    break;
            }
            pc++;
        }
    }
    if (code >= 0) {
        /*
         * Schedule the sampling of any Type 1 screens,
         * and any (Type 1 or Type 3) TransferFunctions.
         * Save the stack depths in case we have to back out.
         */
        uint odepth = ref_stack_count(&o_stack);
        ref odict, odict5;

        odict = op[-1];
        odict5 = *op;
        pop(2);
        op = osp;
        esp += 5;
        make_mark_estack(esp - 4, es_other, sethalftone_cleanup);
        esp[-3] = odict;
        make_istruct(esp - 2, 0, pht);
        make_istruct(esp - 1, 0, pdht);
        make_op_estack(esp, sethalftone_finish);
        for (j = 0; j < count; j++) {
            gx_ht_order *porder = NULL;

            if (pdht->components == 0)
                porder = &pdht->order;
            else {
                /* Find the component in pdht that matches component j in
                   the pht; gs_sethalftone_prepare() may permute these. */
                int k;
                int comp_number = phtc[j].comp_number;
                for (k = 0; k < count; k++) {
                    if (pdht->components[k].comp_number == comp_number) {
                        porder = &pdht->components[k].corder;
                        break;
                    }
                }
            }
            switch (phtc[j].type) {
            case ht_type_spot:
                code = zscreen_enum_init(i_ctx_p, porder,
                                         &phtc[j].params.spot.screen,
                                         &sprocs[j], 0, 0, space_index);
                if (code < 0)
                    break;
                /* falls through */
            case ht_type_threshold:
                if (!r_has_type(tprocs + j, t__invalid)) {
                    /* Schedule TransferFunction sampling. */
                    /****** check_xstack IS WRONG ******/
                    check_ostack(zcolor_remap_one_ostack);
                    check_estack(zcolor_remap_one_estack);
                    code = zcolor_remap_one(i_ctx_p, tprocs + j,
                                            porder->transfer, igs,
                                            zcolor_remap_one_finish);
                    op = osp;
                }
                break;
            default:	/* not possible here, but to keep */
                                /* the compilers happy.... */
                ;
            }
            if (code < 0) {	/* Restore the stack. */
                ref_stack_pop_to(&o_stack, odepth);
                ref_stack_pop_to(&e_stack, edepth);
                op = osp;
                op[-1] = odict;
                *op = odict5;
                break;
            }
            npop = 0;
        }
    }
    if (code < 0) {
        gs_free_object(mem, pdht, ".sethalftone5");
        gs_free_object(mem, phtc, ".sethalftone5");
        gs_free_object(mem, pht, ".sethalftone5");
        return code;
    }
    pop(npop);
    return (ref_stack_count(&e_stack) > edepth ? o_push_estack : 0);
}
예제 #29
0
/* Send the page to the printer. */
static int
m8510_print_page(gx_device_printer *pdev, FILE *prn_stream)
{
	int line_size = gdev_mem_bytes_per_scan_line((gx_device *)pdev);
	byte *in1 = (byte *) gs_malloc(pdev->memory, 8, line_size, "m8510_print_page(in1)");
	byte *in2 = (byte *) gs_malloc(pdev->memory, 8, line_size, "m8510_print_page(in2)");
	byte *out = (byte *) gs_malloc(pdev->memory, 8, line_size, "m8510_print_page(out)");
	int lnum = 0;
	int code = 0;
	byte *inp, *in_end, *outp;
	int i;

	if (in1 == 0 || in2 == 0 || out == 0) {
		code = gs_note_error(gs_error_VMerror);
		goto out;
	}

	/*
	 * Initialize the printer.
	 * NLQ mode, proportional print (160x144 dpi).
	 * and 16/144" linefeeds.
	 */
	fwrite("\033m2\033P\033T16", 1, 9, prn_stream);

	/* Transfer pixels to printer */
	while ( lnum < pdev->height ) {
		/* get a raster */
		for (i = 7; i >= 0; i--) {
			gdev_prn_copy_scan_lines(pdev, lnum, &in1[i*line_size], line_size);
			lnum++;
			gdev_prn_copy_scan_lines(pdev, lnum, &in2[i*line_size], line_size);
			lnum++;
		}

		/* Transpose the 1st pass of data. */
		in_end = in1 + line_size;
		for (inp = in1, outp = out; inp < in_end; inp++, outp += 8)
			gdev_prn_transpose_8x8(inp, line_size, outp, 1);

		/* send the 1st line */
		m8510_output_run(pdev, out, 0, prn_stream);

		/* Transpose the 2nd pass of data. */
		in_end = in2 + line_size;
		for (inp = in2, outp = out; inp < in_end; inp++, outp += 8)
			gdev_prn_transpose_8x8(inp, line_size, outp, 1);

		/* send the 2nd line */
		m8510_output_run(pdev, out, 1, prn_stream);
	}

	/* reset the printer. */
	fwrite("\033c1", 1, 3, prn_stream);
	fflush(prn_stream);

out:;
	if (out) gs_free(pdev->memory, (char *) out, 8, line_size, "m8510_print_page(out)");
	if (in2) gs_free(pdev->memory, (char *) in2, 8, line_size, "m8510_print_page(in2)");
	if (in1) gs_free(pdev->memory, (char *) in1, 8, line_size, "m8510_print_page(in1)");

	return code;
}
예제 #30
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;
}