Beispiel #1
0
/*
 * Compress a bitmap, skipping extra padding bytes at the end of each row if
 * necessary.  We require height >= 1, raster >= bitmap_raster(width_bits).
 */
static int
cmd_compress_bitmap(stream_state * st, const byte * data, uint width_bits,
                    uint raster, uint height, stream_cursor_write * pw)
{
    uint width_bytes = bitmap_raster(width_bits);
    int status = 0;
    stream_cursor_read r;

    r.ptr = data - 1;
    if (raster == width_bytes) {
        r.limit = r.ptr + raster * height;
        status = (*st->templat->process) (st, &r, pw, true);
    } else {			/* Compress row-by-row. */
        uint y;

        for (y = 1; (r.limit = r.ptr + width_bytes), y < height; ++y) {
            status = (*st->templat->process) (st, &r, pw, false);
            if (status)
                break;
            if (r.ptr != r.limit) {	/* We don't attempt to handle compressors that */
                /* require >1 input byte to make progress. */
                status = -1;
                break;
            }
            r.ptr += raster - width_bytes;
        }
        if (status == 0)
            status = (*st->templat->process) (st, &r, pw, true);
    }
    if (st->templat->release)
        (*st->templat->release) (st);
    return status;
}
Beispiel #2
0
/* This is the first half of gs_screen_init_accurate. */
int
gs_screen_order_alloc(gx_ht_order *porder, gs_memory_t *mem)
{
    uint num_levels = porder->params.W * porder->params.D;
    int code;

    if (!FORCE_STRIP_HALFTONES &&
        ((ulong)porder->params.W1 * bitmap_raster(porder->params.W) +
           num_levels * sizeof(*porder->levels) +
           porder->params.W * porder->params.W1 * sizeof(gx_ht_bit)) <=
        porder->screen_params.max_size) {
        /*
         * Allocate an order for the entire tile, but only sample one
         * strip.  Note that this causes the order parameters to be
         * self-inconsistent until gx_ht_construct_spot_order fixes them
         * up: see gxdht.h for more information.
         */
        code = gx_ht_alloc_order(porder, porder->params.W,
                                 porder->params.W1, 0,
                                 num_levels, mem);
        porder->height = porder->orig_height = porder->params.D;
        porder->shift = porder->orig_shift = porder->params.S;
    } else {
        /* Just allocate the order for a single strip. */
        code = gx_ht_alloc_order(porder, porder->params.W,
                                 porder->params.D, porder->params.S,
                                 num_levels, mem);
    }
    return code;
}
Beispiel #3
0
static void
clist_render_thread(void *data)
{
    clist_render_thread_control_t *thread = (clist_render_thread_control_t *)data;
    gx_device *dev = thread->cdev;
    gx_device_clist *cldev = (gx_device_clist *)dev;
    gx_device_clist_reader *crdev = &cldev->reader;
    gx_device *bdev = thread->bdev;
    gs_int_rect band_rect;
    byte *mdata = crdev->data + crdev->page_tile_cache_size;
    uint raster = bitmap_raster(dev->width * dev->color_info.depth);
    int code;
    int band_height = crdev->page_band_height;
    int band = thread->band;
    int band_begin_line = band * band_height;
    int band_end_line = band_begin_line + band_height;
    int band_num_lines;
#ifdef DEBUG
    long starttime[2], endtime[2];

    gp_get_usertime(starttime);	/* thread start time */
#endif
    if (band_end_line > dev->height)
	band_end_line = dev->height;
    band_num_lines = band_end_line - band_begin_line;

    code = crdev->buf_procs.setup_buf_device
	    (bdev, mdata, raster, NULL, 0, band_num_lines, band_num_lines);
    band_rect.p.x = 0;
    band_rect.p.y = band_begin_line;
    band_rect.q.x = dev->width;
    band_rect.q.y = band_end_line;
    if (code >= 0)
	code = clist_render_rectangle(cldev, &band_rect, bdev, NULL, true);
    /* Reset the band boundaries now */
    crdev->ymin = band_begin_line;
    crdev->ymax = band_end_line;
    crdev->offset_map = NULL;
    if (code < 0)
	thread->status = code;		/* shouldn't happen */
    else
	thread->status = RENDER_THREAD_DONE;	/* OK */

#ifdef DEBUG
    gp_get_usertime(endtime);
    thread->cputime += (endtime[0] - starttime[0]) * 1000 +
	     (endtime[1] - starttime[1]) / 1000000;
#endif
    /*
     * Signal the semaphores. We signal the 'group' first since even if
     * the waiter is released on the group, it still needs to check
     * status on the thread
     */
    gx_semaphore_signal(thread->sema_group);
    gx_semaphore_signal(thread->sema_this);
}
Beispiel #4
0
static int
alpha_buffer_init(gs_state * pgs, fixed extra_x, fixed extra_y, int alpha_bits, 
                  bool devn)
{
    gx_device *dev = gs_currentdevice_inline(pgs);
    int log2_alpha_bits = ilog2(alpha_bits);
    gs_fixed_rect bbox;
    gs_int_rect ibox;
    uint width, raster, band_space;
    uint height;
    gs_log2_scale_point log2_scale;
    gs_memory_t *mem;
    gx_device_memory *mdev;

    log2_scale.x = log2_scale.y = log2_alpha_bits;
    gx_path_bbox(pgs->path, &bbox);
    ibox.p.x = fixed2int(bbox.p.x - extra_x) - 1;
    ibox.p.y = fixed2int(bbox.p.y - extra_y) - 1;
    ibox.q.x = fixed2int_ceiling(bbox.q.x + extra_x) + 1;
    ibox.q.y = fixed2int_ceiling(bbox.q.y + extra_y) + 1;
    width = (ibox.q.x - ibox.p.x) << log2_scale.x;
    raster = bitmap_raster(width);
    band_space = raster << log2_scale.y;
    height = (abuf_nominal / band_space) << log2_scale.y;
    if (height == 0)
        height = 1 << log2_scale.y;
    mem = pgs->memory;
    mdev = gs_alloc_struct(mem, gx_device_memory, &st_device_memory,
                           "alpha_buffer_init");
    if (mdev == 0)
        return 0;		/* if no room, don't buffer */
    /* We may have to update the marking parameters if we have a pdf14 device
       as our target.  Need to do while dev is still active in pgs */
    if (dev_proc(dev, dev_spec_op)(dev, gxdso_is_pdf14_device, NULL, 0) > 0) {
        gs_update_trans_marking_params(pgs);
    }
    gs_make_mem_abuf_device(mdev, mem, dev, &log2_scale,
                            alpha_bits, ibox.p.x << log2_scale.x, devn);
    mdev->width = width;
    mdev->height = height;
    mdev->bitmap_memory = mem;
    if ((*dev_proc(mdev, open_device)) ((gx_device *) mdev) < 0) {
        /* No room for bits, punt. */
        gs_free_object(mem, mdev, "alpha_buffer_init");
        return 0;
    }
    gx_set_device_only(pgs, (gx_device *) mdev);
    scale_paths(pgs, log2_scale.x, log2_scale.y, true);
    return 1;
}
/* Determine the space needed by a planar buffer device. */
int
gdev_prn_size_buf_planar(gx_device_buf_space_t *space, gx_device *target,
			 const gx_render_plane_t *render_plane,
			 int height, bool for_band)
{
    gx_device_memory mdev;

    if (render_plane && render_plane->index >= 0)
	return gx_default_size_buf_device(space, target, render_plane,
					  height, for_band);
    mdev.color_info = target->color_info;
    gdev_prn_set_planar(&mdev, target);
    if (gdev_mem_bits_size(&mdev, target->width, height, &(space->bits)) < 0)
	return_error(gs_error_VMerror);
    space->line_ptrs = gdev_mem_line_ptrs_size(&mdev, target->width, height);
    space->raster = bitmap_raster(target->width * mdev.planes[0].depth);
    return 0;
}
Beispiel #6
0
static int
alpha_buffer_init(gs_state * pgs, fixed extra_x, fixed extra_y, int alpha_bits)
{
    gx_device *dev = gs_currentdevice_inline(pgs);
    int log2_alpha_bits = ilog2(alpha_bits);
    gs_fixed_rect bbox;
    gs_int_rect ibox;
    uint width, raster, band_space;
    uint height;
    gs_log2_scale_point log2_scale;
    gs_memory_t *mem;
    gx_device_memory *mdev;

    log2_scale.x = log2_scale.y = log2_alpha_bits;
    gx_path_bbox(pgs->path, &bbox);
    ibox.p.x = fixed2int(bbox.p.x - extra_x) - 1;
    ibox.p.y = fixed2int(bbox.p.y - extra_y) - 1;
    ibox.q.x = fixed2int_ceiling(bbox.q.x + extra_x) + 1;
    ibox.q.y = fixed2int_ceiling(bbox.q.y + extra_y) + 1;
    width = (ibox.q.x - ibox.p.x) << log2_scale.x;
    raster = bitmap_raster(width);
    band_space = raster << log2_scale.y;
    height = (abuf_nominal / band_space) << log2_scale.y;
    if (height == 0)
	height = 1 << log2_scale.y;
    mem = pgs->memory;
    mdev = gs_alloc_struct(mem, gx_device_memory, &st_device_memory,
			   "alpha_buffer_init");
    if (mdev == 0)
	return 0;		/* if no room, don't buffer */
    gs_make_mem_abuf_device(mdev, mem, dev, &log2_scale,
			    alpha_bits, ibox.p.x << log2_scale.x);
    mdev->width = width;
    mdev->height = height;
    mdev->bitmap_memory = mem;
    if ((*dev_proc(mdev, open_device)) ((gx_device *) mdev) < 0) {
	/* No room for bits, punt. */
	gs_free_object(mem, mdev, "alpha_buffer_init");
	return 0;
    }
    gx_set_device_only(pgs, (gx_device *) mdev);
    scale_paths(pgs, log2_scale.x, log2_scale.y, true);
    return 1;
}
Beispiel #7
0
/*
 * Determine the (possibly unpadded) width in bytes for writing a bitmap,
 * per the algorithm in gxcldev.h.  If compression_mask has any of the
 * cmd_mask_compress_any bits set, we assume the bitmap will be compressed.
 * Return the total size of the bitmap.
 */
uint
clist_bitmap_bytes(uint width_bits, uint height, int compression_mask,
                   uint * width_bytes, uint * raster)
{
    uint full_raster = *raster = bitmap_raster(width_bits);
    uint short_raster = (width_bits + 7) >> 3;
    uint width_bytes_last;

    if (compression_mask & cmd_mask_compress_any)
        *width_bytes = width_bytes_last = full_raster;
    else if (short_raster <= cmd_max_short_width_bytes ||
             height <= 1 ||
             (compression_mask & decompress_spread) != 0
        )
        *width_bytes = width_bytes_last = short_raster;
    else
        *width_bytes = full_raster, width_bytes_last = short_raster;
    return
        (height == 0 ? 0 : *width_bytes * (height - 1) + width_bytes_last);
}
Beispiel #8
0
/* rendering adjacent to the first band (forward or backward) */
static int
clist_get_bits_rect_mt(gx_device *dev, const gs_int_rect * prect,
			 gs_get_bits_params_t *params, gs_int_rect **unread)
{
    gx_device_printer *pdev = (gx_device_printer *)dev;
    gx_device_clist *cldev = (gx_device_clist *)dev;
    gx_device_clist_common *cdev = (gx_device_clist_common *)dev;
    gx_device_clist_reader *crdev = &cldev->reader;
    gs_memory_t *mem = cdev->bandlist_memory;
    gs_get_bits_options_t options = params->options;
    int y = prect->p.y;
    int end_y = prect->q.y;
    int line_count = end_y - y;
    int band_height = crdev->page_info.band_params.BandHeight;
    int band = y / band_height;
    gs_int_rect band_rect;
    int lines_rasterized;
    gx_device *bdev;
    byte *mdata;
    uint raster = bitmap_raster(dev->width * dev->color_info.depth);
    int my;
    int code = 0;

    /* This page might not want multiple threads */
    /* Also we don't support plane extraction using multiple threads */
    if (pdev->num_render_threads_requested < 1 || (options & GB_SELECT_PLANES))
	return clist_get_bits_rectangle(dev, prect, params, unread);

    if (prect->p.x < 0 || prect->q.x > dev->width ||
	y < 0 || end_y > dev->height
	)
	return_error(gs_error_rangecheck);
    if (line_count <= 0 || prect->p.x >= prect->q.x)
	return 0;

    if (crdev->ymin < 0) {
	if ((code = clist_close_writer_and_init_reader(cldev)) < 0)
	    return code;
	if (clist_setup_render_threads(dev, y) < 0) 
	    /* problem setting up the threads, revert to single threaded */
	    return clist_get_bits_rectangle(dev, prect, params, unread);
    }
    else {
	if (crdev->render_threads == NULL) {
            /* If we get here with with ymin >=0, it's because we closed the threads */
	    /* while doing a page due to an error. Use single threaded mode.         */
	    return clist_get_bits_rectangle(dev, prect, params, unread);
	}
    }
    /* If we already have the band's data, just return it */
    if (y < crdev->ymin || end_y > crdev->ymax)
	code = clist_get_band_from_thread(dev, band);
    if (code < 0)
	goto free_thread_out;
    mdata = crdev->data + crdev->page_tile_cache_size;
    if ((code = gdev_create_buf_device(cdev->buf_procs.create_buf_device,
				  &bdev, cdev->target, y, NULL,
				  mem, clist_get_band_complexity(dev,y))) < 0 ||
	(code = crdev->buf_procs.setup_buf_device(bdev, mdata, raster, NULL,
			    y - crdev->ymin, line_count, crdev->ymax - crdev->ymin)) < 0)
	goto free_thread_out;

    lines_rasterized = min(band_height, line_count);
    /* Return as much of the rectangle as falls within the rasterized lines. */
    band_rect = *prect;
    band_rect.p.y = 0;
    band_rect.q.y = lines_rasterized;
    code = dev_proc(bdev, get_bits_rectangle)
	(bdev, &band_rect, params, unread);
    cdev->buf_procs.destroy_buf_device(bdev);
    if (code < 0)
	goto free_thread_out;

    /* Note that if called via 'get_bits', the line count will always be 1 */
    if (lines_rasterized == line_count) {
	return code;		
    }

/***** TODO: Handle the below with data from the threads *****/
    /*
     * We'll have to return the rectangle in pieces.  Force GB_RETURN_COPY
     * rather than GB_RETURN_POINTER, and require all subsequent pieces to
     * use the same values as the first piece for all of the other format
     * options.  If copying isn't allowed, or if there are any unread
     * rectangles, punt.
     */
    if (!(options & GB_RETURN_COPY) || code > 0)
	return gx_default_get_bits_rectangle(dev, prect, params, unread);
    options = params->options;
    if (!(options & GB_RETURN_COPY)) {
	/* Redo the first piece with copying. */
	params->options = options =
	    (params->options & ~GB_RETURN_ALL) | GB_RETURN_COPY;
	lines_rasterized = 0;
    }
    {
	gs_get_bits_params_t band_params;
	uint raster = gx_device_raster(bdev, true);

	code = gdev_create_buf_device(cdev->buf_procs.create_buf_device,
				      &bdev, cdev->target, y, NULL,
				      mem, clist_get_band_complexity(dev, y));
	if (code < 0)
	    return code;
	band_params = *params;
	while ((y += lines_rasterized) < end_y) {
	    /* Increment data pointer by lines_rasterized. */
	    if (band_params.data)
		band_params.data[0] += raster * lines_rasterized;
	    line_count = end_y - y;
	    code = clist_rasterize_lines(dev, y, line_count, bdev, NULL, &my);
	    if (code < 0)
		break;
	    lines_rasterized = min(code, line_count);
	    band_rect.p.y = my;
	    band_rect.q.y = my + lines_rasterized;
	    code = dev_proc(bdev, get_bits_rectangle)
		(bdev, &band_rect, &band_params, unread);
	    if (code < 0)
		break;
	    params->options = options = band_params.options;
	    if (lines_rasterized == line_count)
		break;
	}
	cdev->buf_procs.destroy_buf_device(bdev);
    }
    return code;

/* Free up thread stuff */
free_thread_out:
    clist_teardown_render_threads(dev);
    return code;
}
Beispiel #9
0
irender_proc_t
gs_image_class_1_simple(gx_image_enum * penum)
{
    irender_proc_t rproc;
    fixed ox = dda_current(penum->dda.pixel0.x);
    fixed oy = dda_current(penum->dda.pixel0.y);

    if (penum->use_rop || penum->spp != 1 || penum->bps != 1)
        return 0;
    switch (penum->posture) {
        case image_portrait:
            {			/* Use fast portrait algorithm. */
                long dev_width =
                    fixed2long_pixround(ox + penum->x_extent.x) -
                    fixed2long_pixround(ox);

                if (dev_width != penum->rect.w) {
                    /*
                     * Add an extra align_bitmap_mod of padding so that
                     * we can align scaled rows with the device.
                     */
                    long line_size =
                        bitmap_raster(any_abs(dev_width)) + align_bitmap_mod;

                    if (penum->adjust != 0 || line_size > max_uint)
                        return 0;
                    /* Must buffer a scan line. */
                    penum->line_width = any_abs(dev_width);
                    penum->line_size = (uint) line_size;
                    penum->line = gs_alloc_bytes(penum->memory,
                                            penum->line_size, "image line");
                    if (penum->line == 0) {
                        gx_default_end_image(penum->dev,
                                             (gx_image_enum_common_t *)penum,
                                             false);
                        return 0;
                    }
                }
                if_debug2('b', "[b]render=simple, unpack=copy; rect.w=%d, dev_width=%ld\n",
                          penum->rect.w, dev_width);
                rproc = image_render_simple;
                break;
            }
        case image_landscape:
            {			/* Use fast landscape algorithm. */
                long dev_width =
                    fixed2long_pixround(oy + penum->x_extent.y) -
                    fixed2long_pixround(oy);
                long line_size =
                    (dev_width = any_abs(dev_width),
                     bitmap_raster(dev_width) * 8 +
                     ROUND_UP(dev_width, 8) * align_bitmap_mod);

                if ((dev_width != penum->rect.w && penum->adjust != 0) ||
                    line_size > max_uint
                    )
                    return 0;
                /* Must buffer a group of 8N scan lines. */
                penum->line_width = dev_width;
                penum->line_size = (uint) line_size;
                penum->line = gs_alloc_bytes(penum->memory,
                                             penum->line_size, "image line");
                if (penum->line == 0) {
                    gx_default_end_image(penum->dev,
                                         (gx_image_enum_common_t *) penum,
                                         false);
                    return 0;
                }
                penum->xi_next = penum->line_xy = fixed2int_var_rounded(ox);
                if_debug3('b', "[b]render=landscape, unpack=copy; rect.w=%d, dev_width=%ld, line_size=%ld\n",
                          penum->rect.w, dev_width, line_size);
                rproc = image_render_landscape;
                /* Precompute values needed for rasterizing. */
                penum->dxy =
                    float2fixed(penum->matrix.xy +
                                fixed2float(fixed_epsilon) / 2);
                break;
            }
        default:
            return 0;
    }
    /* Precompute values needed for rasterizing. */
    penum->dxx =
        float2fixed(penum->matrix.xx + fixed2float(fixed_epsilon) / 2);
    /*
     * We don't want to spread the samples, but we have to reset unpack_bps
     * to prevent the buffer pointer from being incremented by 8 bytes per
     * input byte.
     */
    penum->unpack = sample_unpack_copy;
    penum->unpack_bps = 8;
    if (penum->use_mask_color) {
        /*
         * Set the masked color as 'no_color' to make it transparent
         *  according to the mask color range and the decoding.
         */
        penum->masked = true;
        if (penum->mask_color.values[0] == 1) {
            /* if v0 == 1, 1 is transparent since v1 must be == 1 to be a valid range */
            set_nonclient_dev_color(penum->map[0].inverted ? penum->icolor0 : penum->icolor1,
                        gx_no_color_index);
        } else if (penum->mask_color.values[1] == 0) {
            /* if v1 == 0, 0 is transparent since v0 must be == 0 to be a valid range */
            set_nonclient_dev_color(penum->map[0].inverted ? penum->icolor1 : penum->icolor0,
                        gx_no_color_index);
        } else {
            /*
             * The only other possible in-range value is v0 = 0, v1 = 1.
             * The image is completely transparent!
             */
            rproc = image_render_skip;
        }
        penum->map[0].decoding = sd_none;
    }
    return rproc;
}
Beispiel #10
0
/* the routine sets ph->actual_frequency and ph->actual_angle. */
static int
pick_cell_size(gs_screen_halftone * ph, const gs_matrix * pmat, ulong max_size,
               uint min_levels, bool accurate, gx_ht_cell_params_t * phcp)
{
    const bool landscape = (pmat->xy != 0.0 || pmat->yx != 0.0);

    /* Account for a possibly reflected coordinate system. */
    /* See gxstroke.c for the algorithm. */
    const bool reflected = pmat->xy * pmat->yx > pmat->xx * pmat->yy;
    const int reflection = (reflected ? -1 : 1);
    const int rotation =
    (landscape ? (pmat->yx < 0 ? 90 : -90) : pmat->xx < 0 ? 180 : 0);
    const double f0 = ph->frequency, a0 = ph->angle;
    const double T =
    fabs((landscape ? pmat->yx / pmat->xy : pmat->xx / pmat->yy));
    gs_point uv0;

#define u0 uv0.x
#define v0 uv0.y
    int rt = 1;
    double f = 0, a = 0;
    double e_best = 1000;
    bool better;

    /*
     * We need to find a vector in device space whose length is
     * 1 inch / ph->frequency and whose angle is ph->angle.
     * Because device pixels may not be square, we can't simply
     * map the length to device space and then rotate it;
     * instead, since we know that user space is uniform in X and Y,
     * we calculate the correct angle in user space before rotation.
     */

    /* Compute trial values of u and v. */

    {
        gs_matrix rmat;

        gs_make_rotation(a0 * reflection + rotation, &rmat);
        gs_distance_transform(72.0 / f0, 0.0, &rmat, &uv0);
        gs_distance_transform(u0, v0, pmat, &uv0);
        if_debug10('h', "[h]Requested: f=%g a=%g mat=[%g %g %g %g] max_size=%lu min_levels=%u =>\n     u=%g v=%g\n",
                   ph->frequency, ph->angle,
                   pmat->xx, pmat->xy, pmat->yx, pmat->yy,
                   max_size, min_levels, u0, v0);
    }

    /* Adjust u and v to reasonable values. */

    if (u0 == 0 && v0 == 0)
        return_error(gs_error_rangecheck);
    while ((fabs(u0) + fabs(v0)) * rt < 4)
        ++rt;
  try_size:
    better = false;
    {
        double fm0 = u0 * rt;
        double fn0 = v0 * rt;
        int m0 = (int)floor(u0 * rt + 0.0001);
        int n0 = (int)floor(v0 * rt + 0.0001);
        gx_ht_cell_params_t p;

        p.R = p.R1 = rt;
        for (p.M = m0 + 1; p.M >= m0; p.M--)
            for (p.N = n0 + 1; p.N >= n0; p.N--) {
                long raster, wt, wt_size;
                double fr, ar, ft, at, f_diff, a_diff, f_err, a_err;

                p.M1 = (int)floor(p.M / T + 0.5);
                p.N1 = (int)floor(p.N * T + 0.5);
                gx_compute_cell_values(&p);
                if_debug3('h', "[h]trying m=%d, n=%d, r=%d\n", p.M, p.N, rt);
                wt = p.W;
                if (wt >= max_short)
                    continue;
                /* Check the strip size, not the full tile size, */
                /* against max_size. */
                raster = bitmap_raster(wt);
                if (raster > max_size / p.D || raster > max_long / wt)
                    continue;
                wt_size = raster * wt;

                /* Compute the corresponding values of F and A. */

                if (landscape)
                    ar = atan2(p.M * pmat->xy, p.N * pmat->yx),
                        fr = 72.0 * (p.M == 0 ? pmat->xy / p.N * cos(ar) :
                                     pmat->yx / p.M * sin(ar));
                else
                    ar = atan2(p.N * pmat->xx, p.M * pmat->yy),
                        fr = 72.0 * (p.M == 0 ? pmat->yy / p.N * sin(ar) :
                                     pmat->xx / p.M * cos(ar));
                ft = fabs(fr) * rt;
                /* Normalize the angle to the requested quadrant. */
                at = (ar * radians_to_degrees - rotation) * reflection;
                at -= floor(at / 180.0) * 180.0;
                at += floor(a0 / 180.0) * 180.0;
                f_diff = fabs(ft - f0);
                a_diff = fabs(at - a0);
                f_err = f_diff / fabs(f0);
                /*
                 * We used to compute the percentage difference here:
                 *      a_err = (a0 == 0 ? a_diff : a_diff / fabs(a0));
                 * but using the angle difference makes more sense:
                 */
                a_err = a_diff;

                if_debug5('h', " ==> d=%d, wt=%ld, wt_size=%ld, f=%g, a=%g\n",
                          p.D, wt, bitmap_raster(wt) * wt, ft, at);

                {
                    /*
                     * Compute the error in position between ideal location.
                     * and the current integer location.
                     */

                    double error =
                        (fn0 - p.N) * (fn0 - p.N) + (fm0 - p.M) * (fm0 - p.M);
                    /*
                     * Adjust the error by the length of the vector.  This gives
                     * a slight bias toward larger cell sizzes.
                     */
                    error /= p.N * p.N + p.M * p.M;
                    error = sqrt(error); /* The previous calcs. gave value squared */
                    if (error > e_best)
                        continue;
                    e_best = error;
                }
                *phcp = p;
                f = ft, a = at;
                better = true;
                if_debug3('h', "*** best wt_size=%ld, f_diff=%g, a_diff=%g\n",
                          wt_size, f_diff, a_diff);
                /*
                 * We want a maximum relative frequency error of 1% and a
                 * maximum angle error of 1% (of 90 degrees).
                 */
                if (f_err <= 0.01 && a_err <= 0.9 /*degrees*/)
                    goto done;
            }
    }
    if (phcp->C < min_levels) { /* We don't have enough levels yet.  Keep going. */
        ++rt;
        goto try_size;
    }
    if (better) {               /* If we want accurate screens, continue till we fail. */
        if (accurate) {
            ++rt;
            goto try_size;
        }
    } else {                    /*
                                 * We couldn't find an acceptable M and N.  If R > 1,
                                 * take what we've got; if R = 1, give up.
                                 */
        if (rt == 1)
            return_error(gs_error_rangecheck);
    }

    /* Deliver the results. */
  done:
    if_debug5('h', "[h]Chosen: f=%g a=%g M=%d N=%d R=%d\n",
              f, a, phcp->M, phcp->N, phcp->R);
    ph->actual_frequency = f;
    ph->actual_angle = a;
    return 0;
#undef u0
#undef v0
}
Beispiel #11
0
/*
 * 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;
}