Exemplo n.º 1
0
void PixmanBitmap::FlipBlit(int x, int y, Bitmap* _src, Rect src_rect, bool horizontal, bool vertical) {
	if (!horizontal && !vertical) {
		Blit(x, y, _src, src_rect, 255);
		return;
	}

	PixmanBitmap* src = (PixmanBitmap*) _src;

	pixman_transform_t xform;
	pixman_transform_init_scale(&xform,
								pixman_int_to_fixed(horizontal ? -1 : 1),
								pixman_int_to_fixed(vertical ? -1 : 1));

	pixman_transform_translate((pixman_transform_t*) NULL, &xform,
							   pixman_int_to_fixed(horizontal ? src_rect.width : 0),
							   pixman_int_to_fixed(vertical ? src_rect.height : 0));

	pixman_image_set_transform(bitmap, &xform);

	pixman_image_composite32(PIXMAN_OP_SRC,
							 src->bitmap, (pixman_image_t*) NULL, bitmap,
							 src_rect.x, src_rect.y,
							 0, 0,
							 x, y,
							 src_rect.width, src_rect.height);

	pixman_transform_init_identity(&xform);
	pixman_image_set_transform(bitmap, &xform);

	RefreshCallback();
}
Exemplo n.º 2
0
/*
 * Initialize one edge structure given a line, starting y value
 * and a pixel offset for the line
 */
PIXMAN_EXPORT void
pixman_line_fixed_edge_init (pixman_edge_t *            e,
                             int                        n,
                             pixman_fixed_t             y,
                             const pixman_line_fixed_t *line,
                             int                        x_off,
                             int                        y_off)
{
    pixman_fixed_t x_off_fixed = pixman_int_to_fixed (x_off);
    pixman_fixed_t y_off_fixed = pixman_int_to_fixed (y_off);
    const pixman_point_fixed_t *top, *bot;

    if (line->p1.y <= line->p2.y)
    {
	top = &line->p1;
	bot = &line->p2;
    }
    else
    {
	top = &line->p2;
	bot = &line->p1;
    }
    
    pixman_edge_init (e, n, y,
                      top->x + x_off_fixed,
                      top->y + y_off_fixed,
                      bot->x + x_off_fixed,
                      bot->y + y_off_fixed);
}
Exemplo n.º 3
0
/* This function is copied verbatim from pixman.c. */
static pixman_bool_t
compute_transformed_extents (pixman_transform_t   *transform,
			     const pixman_box32_t *extents,
			     box_48_16_t          *transformed)
{
    pixman_fixed_48_16_t tx1, ty1, tx2, ty2;
    pixman_fixed_t x1, y1, x2, y2;
    int i;

    x1 = pixman_int_to_fixed (extents->x1) + pixman_fixed_1 / 2;
    y1 = pixman_int_to_fixed (extents->y1) + pixman_fixed_1 / 2;
    x2 = pixman_int_to_fixed (extents->x2) - pixman_fixed_1 / 2;
    y2 = pixman_int_to_fixed (extents->y2) - pixman_fixed_1 / 2;

    if (!transform)
    {
	transformed->x1 = x1;
	transformed->y1 = y1;
	transformed->x2 = x2;
	transformed->y2 = y2;

	return TRUE;
    }

    tx1 = ty1 = INT64_MAX;
    tx2 = ty2 = INT64_MIN;

    for (i = 0; i < 4; ++i)
    {
	pixman_fixed_48_16_t tx, ty;
	pixman_vector_t v;

	v.vector[0] = (i & 0x01)? x1 : x2;
	v.vector[1] = (i & 0x02)? y1 : y2;
	v.vector[2] = pixman_fixed_1;

	if (!pixman_transform_point (transform, &v))
	    return FALSE;

	tx = (pixman_fixed_48_16_t)v.vector[0];
	ty = (pixman_fixed_48_16_t)v.vector[1];

	if (tx < tx1)
	    tx1 = tx;
	if (ty < ty1)
	    ty1 = ty;
	if (tx > tx2)
	    tx2 = tx;
	if (ty > ty2)
	    ty2 = ty;
    }

    transformed->x1 = tx1;
    transformed->y1 = ty1;
    transformed->x2 = tx2;
    transformed->y2 = ty2;

    return TRUE;
}
Exemplo n.º 4
0
PIXMAN_EXPORT void
pixman_add_traps (pixman_image_t * image,
                  int16_t          x_off,
                  int16_t          y_off,
                  int              ntrap,
                  pixman_trap_t *  traps)
{
    int bpp;
    int width;
    int height;

    pixman_fixed_t x_off_fixed;
    pixman_fixed_t y_off_fixed;
    pixman_edge_t l, r;
    pixman_fixed_t t, b;

    _pixman_image_validate (image);
    
    width = image->bits.width;
    height = image->bits.height;
    bpp = PIXMAN_FORMAT_BPP (image->bits.format);

    x_off_fixed = pixman_int_to_fixed (x_off);
    y_off_fixed = pixman_int_to_fixed (y_off);

    while (ntrap--)
    {
	t = traps->top.y + y_off_fixed;
	if (t < 0)
	    t = 0;
	t = pixman_sample_ceil_y (t, bpp);

	b = traps->bot.y + y_off_fixed;
	if (pixman_fixed_to_int (b) >= height)
	    b = pixman_int_to_fixed (height) - 1;
	b = pixman_sample_floor_y (b, bpp);

	if (b >= t)
	{
	    /* initialize edge walkers */
	    pixman_edge_init (&l, bpp, t,
	                      traps->top.l + x_off_fixed,
	                      traps->top.y + y_off_fixed,
	                      traps->bot.l + x_off_fixed,
	                      traps->bot.y + y_off_fixed);

	    pixman_edge_init (&r, bpp, t,
	                      traps->top.r + x_off_fixed,
	                      traps->top.y + y_off_fixed,
	                      traps->bot.r + x_off_fixed,
	                      traps->bot.y + y_off_fixed);

	    pixman_rasterize_edges (image, &l, &r, t, b);
	}

	traps++;
    }
}
Exemplo n.º 5
0
static void
bench (const bench_info_t *bi,
       uint32_t            max_n,
       uint32_t            max_time,
       uint32_t           *ret_n,
       uint32_t           *ret_time,
       void              (*func) (const pixman_composite_info_t *info))
{
    uint32_t n = 0;
    uint32_t t0;
    uint32_t t1;
    uint32_t x = 0;
    pixman_transform_t t;
    pixman_composite_info_t info;

    t = bi->transform;
    info.op = bi->op;
    info.src_image = bi->src_image;
    info.mask_image = bi->mask_image;
    info.dest_image = bi->dest_image;
    info.src_x = 0;
    info.src_y = 0;
    info.mask_x = 0;
    info.mask_y = 0;
    /* info.dest_x set below */
    info.dest_y = 0;
    info.width = WIDTH;
    info.height = HEIGHT;

    t0 = gettimei ();

    do
    {

        if (++x >= 64)
            x = 0;

        info.dest_x = 63 - x;

        t.matrix[0][2] = pixman_int_to_fixed (bi->src_x + x);
        t.matrix[1][2] = pixman_int_to_fixed (bi->src_y);
        pixman_image_set_transform (bi->src_image, &t);

        if (bi->mask_image)
            pixman_image_set_transform (bi->mask_image, &t);

        func (&info);
        t1 = gettimei ();
    }
    while (++n < max_n && (t1 - t0) < max_time);

    if (ret_n)
        *ret_n = n;

    *ret_time = t1 - t0;
}
Exemplo n.º 6
0
static uint32_t *
bits_image_fetch_affine_no_alpha (pixman_iter_t *  iter,
				  const uint32_t * mask)
{
    pixman_image_t *image  = iter->image;
    int             offset = iter->x;
    int             line   = iter->y++;
    int             width  = iter->width;
    uint32_t *      buffer = iter->buffer;

    pixman_fixed_t x, y;
    pixman_fixed_t ux, uy;
    pixman_vector_t v;
    int i;

    /* reference point is the center of the pixel */
    v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
    v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
    v.vector[2] = pixman_fixed_1;

    if (image->common.transform)
    {
	if (!pixman_transform_point_3d (image->common.transform, &v))
	    return iter->buffer;

	ux = image->common.transform->matrix[0][0];
	uy = image->common.transform->matrix[1][0];
    }
    else
    {
	ux = pixman_fixed_1;
	uy = 0;
    }

    x = v.vector[0];
    y = v.vector[1];

    for (i = 0; i < width; ++i)
    {
	if (!mask || mask[i])
	{
	    buffer[i] = bits_image_fetch_pixel_filtered (
		&image->bits, x, y, fetch_pixel_no_alpha);
	}

	x += ux;
	y += uy;
    }

    return buffer;
}
Exemplo n.º 7
0
static void
ssse3_bilinear_cover_iter_init (pixman_iter_t *iter, const pixman_iter_info_t *iter_info)
{
    int width = iter->width;
    bilinear_info_t *info;
    pixman_vector_t v;

    /* Reference point is the center of the pixel */
    v.vector[0] = pixman_int_to_fixed (iter->x) + pixman_fixed_1 / 2;
    v.vector[1] = pixman_int_to_fixed (iter->y) + pixman_fixed_1 / 2;
    v.vector[2] = pixman_fixed_1;

    if (!pixman_transform_point_3d (iter->image->common.transform, &v))
	goto fail;

    info = malloc (sizeof (*info) + (2 * width - 1) * sizeof (uint64_t) + 64);
    if (!info)
	goto fail;

    info->x = v.vector[0] - pixman_fixed_1 / 2;
    info->y = v.vector[1] - pixman_fixed_1 / 2;

#define ALIGN(addr)							\
    ((void *)((((uintptr_t)(addr)) + 15) & (~15)))

    /* It is safe to set the y coordinates to -1 initially
     * because COVER_CLIP_BILINEAR ensures that we will only
     * be asked to fetch lines in the [0, height) interval
     */
    info->lines[0].y = -1;
    info->lines[0].buffer = ALIGN (&(info->data[0]));
    info->lines[1].y = -1;
    info->lines[1].buffer = ALIGN (info->lines[0].buffer + width);

    iter->get_scanline = ssse3_fetch_bilinear_cover;
    iter->fini = ssse3_bilinear_cover_iter_fini;

    iter->data = info;
    return;

fail:
    /* Something went wrong, either a bad matrix or OOM; in such cases,
     * we don't guarantee any particular rendering.
     */
    _pixman_log_error (
	FUNC, "Allocation failure or bad matrix, skipping rendering\n");
    
    iter->get_scanline = _pixman_iter_get_scanline_noop;
    iter->fini = NULL;
}
Exemplo n.º 8
0
PIXMAN_EXPORT void
pixman_rasterize_trapezoid (pixman_image_t *          image,
                            const pixman_trapezoid_t *trap,
                            int                       x_off,
                            int                       y_off)
{
    int bpp;
    int width;
    int height;

    pixman_fixed_t x_off_fixed;
    pixman_fixed_t y_off_fixed;
    pixman_edge_t l, r;
    pixman_fixed_t t, b;

    return_if_fail (image->type == BITS);

    _pixman_image_validate (image);
    
    if (!pixman_trapezoid_valid (trap))
	return;

    width = image->bits.width;
    height = image->bits.height;
    bpp = PIXMAN_FORMAT_BPP (image->bits.format);

    x_off_fixed = pixman_int_to_fixed (x_off);
    y_off_fixed = pixman_int_to_fixed (y_off);

    t = trap->top + y_off_fixed;
    if (t < 0)
	t = 0;
    t = pixman_sample_ceil_y (t, bpp);

    b = trap->bottom + y_off_fixed;
    if (pixman_fixed_to_int (b) >= height)
	b = pixman_int_to_fixed (height) - 1;
    b = pixman_sample_floor_y (b, bpp);
    
    if (b >= t)
    {
	/* initialize edge walkers */
	pixman_line_fixed_edge_init (&l, bpp, t, &trap->left, x_off, y_off);
	pixman_line_fixed_edge_init (&r, bpp, t, &trap->right, x_off, y_off);

	pixman_rasterize_edges (image, &l, &r, t, b);
    }
}
Exemplo n.º 9
0
/* Create the parameter list for a SEPARABLE_CONVOLUTION filter
 * with the given kernels and scale parameters
 */
PIXMAN_EXPORT pixman_fixed_t *
pixman_filter_create_separable_convolution (int             *n_values,
					    pixman_fixed_t   scale_x,
					    pixman_fixed_t   scale_y,
					    pixman_kernel_t  reconstruct_x,
					    pixman_kernel_t  reconstruct_y,
					    pixman_kernel_t  sample_x,
					    pixman_kernel_t  sample_y,
					    int              subsample_bits_x,
					    int	             subsample_bits_y)
{
    double sx = fabs (pixman_fixed_to_double (scale_x));
    double sy = fabs (pixman_fixed_to_double (scale_y));
    pixman_fixed_t *horz = NULL, *vert = NULL, *params = NULL;
    int subsample_x, subsample_y;
    int width, height;

    subsample_x = (1 << subsample_bits_x);
    subsample_y = (1 << subsample_bits_y);

    horz = create_1d_filter (&width, reconstruct_x, sample_x, sx, subsample_x);
    vert = create_1d_filter (&height, reconstruct_y, sample_y, sy, subsample_y);

    if (!horz || !vert)
        goto out;
    
    *n_values = 4 + width * subsample_x + height * subsample_y;
    
    params = malloc (*n_values * sizeof (pixman_fixed_t));
    if (!params)
        goto out;

    params[0] = pixman_int_to_fixed (width);
    params[1] = pixman_int_to_fixed (height);
    params[2] = pixman_int_to_fixed (subsample_bits_x);
    params[3] = pixman_int_to_fixed (subsample_bits_y);

    memcpy (params + 4, horz,
	    width * subsample_x * sizeof (pixman_fixed_t));
    memcpy (params + 4 + width * subsample_x, vert,
	    height * subsample_y * sizeof (pixman_fixed_t));

out:
    free (horz);
    free (vert);

    return params;
}
Exemplo n.º 10
0
PIXMAN_EXPORT pixman_image_t *
pixman_image_create_conical_gradient (pixman_point_fixed_t *        center,
                                      pixman_fixed_t                angle,
                                      const pixman_gradient_stop_t *stops,
                                      int                           n_stops)
{
    pixman_image_t *image = _pixman_image_allocate ();
    conical_gradient_t *conical;

    if (!image)
        return NULL;

    conical = &image->conical;

    if (!_pixman_init_gradient (&conical->common, stops, n_stops))
    {
        free (image);
        return NULL;
    }

    angle = MOD (angle, pixman_int_to_fixed (360));

    image->type = CONICAL;

    conical->center = *center;
    conical->angle = (pixman_fixed_to_double (angle) / 180.0) * M_PI;

    return image;
}
Exemplo n.º 11
0
void
joy_filter_gaussian_set_radius(JoyFilter *self, gdouble radius)
{
	g_return_if_fail(JOY_IS_FILTER_GAUSSIAN(self));
	struct Private *priv = GET_PRIVATE(self);
	g_free(priv->kernel);
	gdouble fradius = fabs(radius) + 1.;
	gdouble sigma = sqrt(-(fradius * fradius) / (2. * log(1. / 255.)));
	const gdouble s2 = 2. * sigma * sigma;
	const gdouble s1 = 1. / (G_PI * s2);
	const gint size = 2 * radius + 1;
	gint n = size * size;
	gdouble kernel[n], sum;
	gint i, x, y;
	for (i = 0, sum = 0, x = -radius; x <= radius; ++x) {
		for (y = -radius; y <= radius; ++y, ++i) {
			const gdouble u = x * x;
			const gdouble v = y * y;
			kernel[i] = s1 * exp(-(u + v) / s2);
			sum += kernel[i];
		}
	}
	priv->kernel = g_new(pixman_fixed_t, n + 2);
	priv->kernel[0] = priv->kernel[1] = pixman_int_to_fixed(size);
	for (i = 2; i < n; ++i) {
		priv->kernel[i] = pixman_double_to_fixed(kernel[i] / sum);
	}
	priv->n = n + 2;
	priv->radius = radius;
}
Exemplo n.º 12
0
static int
pixman_renderer_read_pixels(struct weston_output *output,
			       pixman_format_code_t format, void *pixels,
			       uint32_t x, uint32_t y,
			       uint32_t width, uint32_t height)
{
	struct pixman_output_state *po = get_output_state(output);
	pixman_transform_t transform;
	pixman_image_t *out_buf;

	if (!po->hw_buffer) {
		errno = ENODEV;
		return -1;
	}

	out_buf = pixman_image_create_bits(format,
		width,
		height,
		pixels,
		(PIXMAN_FORMAT_BPP(format) / 8) * width);

	/* Caller expects vflipped source image */
	pixman_transform_init_translate(&transform,
					pixman_int_to_fixed (x),
					pixman_int_to_fixed (y - pixman_image_get_height (po->hw_buffer)));
	pixman_transform_scale(&transform, NULL,
			       pixman_fixed_1,
			       pixman_fixed_minus_1);
	pixman_image_set_transform(po->hw_buffer, &transform);

	pixman_image_composite32(PIXMAN_OP_SRC,
				 po->hw_buffer, /* src */
				 NULL /* mask */,
				 out_buf, /* dest */
				 0, 0, /* src_x, src_y */
				 0, 0, /* mask_x, mask_y */
				 0, 0, /* dest_x, dest_y */
				 pixman_image_get_width (po->hw_buffer), /* width */
				 pixman_image_get_height (po->hw_buffer) /* height */);
	pixman_image_set_transform(po->hw_buffer, NULL);

	pixman_image_unref(out_buf);

	return 0;
}
Exemplo n.º 13
0
pixman_fixed_t*
create_gaussian_blur_kernel (gint    radius,
                             gdouble sigma,
                             gint*   length)
{
	const gdouble   scale2 = 2.0f * sigma * sigma;
	const gdouble   scale1 = 1.0f / (G_PI * scale2);
	const gint      size = 2 * radius + 1;
	const gint      n_params = size * size;
	pixman_fixed_t* params;
	gdouble*        tmp;
	gdouble         sum;
	gint            x;
	gint            y;
	gint            i;

        tmp = g_newa (double, n_params);

        // caluclate gaussian kernel in floating point format
        for (i = 0, sum = 0, x = -radius; x <= radius; ++x) {
                for (y = -radius; y <= radius; ++y, ++i) {
                        const gdouble u = x * x;
                        const gdouble v = y * y;

                        tmp[i] = scale1 * exp (-(u+v)/scale2);

                        sum += tmp[i];
                }
        }

        // normalize gaussian kernel and convert to fixed point format
        params = g_new (pixman_fixed_t, n_params + 2);

        params[0] = pixman_int_to_fixed (size);
        params[1] = pixman_int_to_fixed (size);

        for (i = 0; i < n_params; ++i)
                params[2 + i] = pixman_double_to_fixed (tmp[i] / sum);

        if (length)
                *length = n_params + 2;

        return params;
}
Exemplo n.º 14
0
void PixmanBitmap::TiledBlit(int ox, int oy, Rect src_rect, Bitmap* src, Rect dst_rect, int opacity) {
	if (opacity < 0)
		return;

	if (opacity > 255) opacity = 255;

	if (ox >= src_rect.width)	ox %= src_rect.width;
	if (oy >= src_rect.height)	ox %= src_rect.height;
	if (ox < 0) ox += src_rect.width  * ((-ox + src_rect.width  - 1) / src_rect.width);
	if (oy < 0) oy += src_rect.height * ((-oy + src_rect.height - 1) / src_rect.height);

	pixman_image_t* src_bm = GetSubimage(src, src_rect);

	pixman_image_t* mask;
	if (opacity < 255) {
		pixman_color_t tcolor = {0, 0, 0, opacity << 8};
		mask = pixman_image_create_solid_fill(&tcolor);
	}
	else
		mask = (pixman_image_t*) NULL;

	pixman_image_set_repeat(src_bm, PIXMAN_REPEAT_NORMAL);

	pixman_transform_t xform;
	pixman_transform_init_translate(&xform,
									pixman_int_to_fixed(ox),
									pixman_int_to_fixed(oy));

	pixman_image_set_transform(src_bm, &xform);

	pixman_image_composite32(PIXMAN_OP_OVER,
							 src_bm, mask, bitmap,
							 0, 0,
							 0, 0,
							 dst_rect.x, dst_rect.y,
							 dst_rect.width, dst_rect.height);

	pixman_image_unref(src_bm);

	if (mask != NULL)
		pixman_image_unref(mask);

	RefreshCallback();
}
Exemplo n.º 15
0
struct fp_img *fpi_im_resize(struct fp_img *img, unsigned int w_factor, unsigned int h_factor)
{
	int new_width = img->width * w_factor;
	int new_height = img->height * h_factor;
	pixman_image_t *orig, *resized;
	pixman_transform_t transform;
	struct fp_img *newimg;

	orig = pixman_image_create_bits(PIXMAN_a8, img->width, img->height, (uint32_t *)img->data, img->width);
	resized = pixman_image_create_bits(PIXMAN_a8, new_width, new_height, NULL, new_width);

	pixman_transform_init_identity(&transform);
	pixman_transform_scale(NULL, &transform, pixman_int_to_fixed(w_factor), pixman_int_to_fixed(h_factor));
	pixman_image_set_transform(orig, &transform);
	pixman_image_set_filter(orig, PIXMAN_FILTER_BILINEAR, NULL, 0);
	pixman_image_composite32(PIXMAN_OP_SRC,
		orig, /* src */
		NULL, /* mask */
		resized, /* dst */
		0, 0, /* src x y */
		0, 0, /* mask x y */
		0, 0, /* dst x y */
		new_width, new_height /* width height */
		);

	newimg = fpi_img_new(new_width * new_height);
	newimg->width = new_width;
	newimg->height = new_height;
	newimg->flags = img->flags;

	memcpy(newimg->data, pixman_image_get_data(resized), new_width * new_height);

	pixman_image_unref(orig);
	pixman_image_unref(resized);

	return newimg;
}
Exemplo n.º 16
0
static void process_image_data(struct fp_img_dev *dev, char **output, int *output_height)
{
    //pixman stuff taken from libfprint/pixman.c, adapted for my purposes.
    pixman_image_t *orig, *resized;
    pixman_transform_t transform;
    struct vfs0050_dev *vfs_dev = dev->priv;
    struct vfs0050_line *line, *calibration_line;
    char *buf = malloc(vfs_dev->scanbuf_idx);
    int lines = vfs_dev->scanbuf_idx / VFS0050_FRAME_SIZE;
    int i, x, sum, last_sum, diff;
    int new_height;
    //just grab one around middle, there should be 100
    calibration_line = (struct vfs0050_line *) ((char *) vfs_dev->calbuf + (50 * VFS0050_FRAME_SIZE));

    new_height = 0;
    for (i = 0; i < lines; i++) {
        line = (struct vfs0050_line *) ((char *) vfs_dev->scanbuf + (i * VFS0050_FRAME_SIZE));
        if (!is_noise(line))
            memcpy(buf + (new_height++ * VFS0050_IMG_WIDTH), line->row, VFS0050_IMG_WIDTH);
        else
            fp_dbg("removed noise at line: %d\n", i);
    }

    orig = pixman_image_create_bits(PIXMAN_a8, VFS0050_IMG_WIDTH, new_height, (uint32_t *) buf, VFS0050_IMG_WIDTH);
    new_height *= VFS0050_SCALE_FACTOR; //scale for resized image
    resized = pixman_image_create_bits(PIXMAN_a8, VFS0050_IMG_WIDTH, new_height, NULL, VFS0050_IMG_WIDTH);
    pixman_transform_init_identity(&transform);
    pixman_transform_scale(NULL, &transform, pixman_int_to_fixed(1), pixman_double_to_fixed(0.2));
    pixman_image_set_transform(orig, &transform);
    pixman_image_set_filter(orig, PIXMAN_FILTER_BEST, NULL, 0);
    pixman_image_composite32(PIXMAN_OP_SRC,
                             orig,
                             NULL,
                             resized,
                             0, 0,
                             0, 0,
                             0, 0,
                             VFS0050_IMG_WIDTH, new_height
                            );
    memcpy(buf, pixman_image_get_data(resized), VFS0050_IMG_WIDTH * new_height);

    pixman_image_unref(orig);
    pixman_image_unref(resized);

    *output_height = new_height;
    *output = buf;
}
Exemplo n.º 17
0
bool mSDLSWInit(struct mSDLRenderer* renderer) {
#if !SDL_VERSION_ATLEAST(2, 0, 0)
#ifdef COLOR_16_BIT
	SDL_SetVideoMode(renderer->viewportWidth, renderer->viewportHeight, 16, SDL_DOUBLEBUF | SDL_HWSURFACE);
#else
	SDL_SetVideoMode(renderer->viewportWidth, renderer->viewportHeight, 32, SDL_DOUBLEBUF | SDL_HWSURFACE);
#endif
#endif

	unsigned width, height;
	renderer->core->desiredVideoDimensions(renderer->core, &width, &height);
#if SDL_VERSION_ATLEAST(2, 0, 0)
	renderer->window = SDL_CreateWindow(projectName, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, renderer->viewportWidth, renderer->viewportHeight, SDL_WINDOW_OPENGL | (SDL_WINDOW_FULLSCREEN_DESKTOP * renderer->player.fullscreen));
	SDL_GetWindowSize(renderer->window, &renderer->viewportWidth, &renderer->viewportHeight);
	renderer->player.window = renderer->window;
	renderer->sdlRenderer = SDL_CreateRenderer(renderer->window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
#ifdef COLOR_16_BIT
#ifdef COLOR_5_6_5
	renderer->sdlTex = SDL_CreateTexture(renderer->sdlRenderer, SDL_PIXELFORMAT_RGB565, SDL_TEXTUREACCESS_STREAMING, width, height);
#else
	renderer->sdlTex = SDL_CreateTexture(renderer->sdlRenderer, SDL_PIXELFORMAT_ABGR1555, SDL_TEXTUREACCESS_STREAMING, width, height);
#endif
#else
	renderer->sdlTex = SDL_CreateTexture(renderer->sdlRenderer, SDL_PIXELFORMAT_ABGR8888, SDL_TEXTUREACCESS_STREAMING, width, height);
#endif

	int stride;
	SDL_LockTexture(renderer->sdlTex, 0, (void**) &renderer->outputBuffer, &stride);
	renderer->core->setVideoBuffer(renderer->core, renderer->outputBuffer, stride / BYTES_PER_PIXEL);
#else
	SDL_Surface* surface = SDL_GetVideoSurface();
	SDL_LockSurface(surface);

	if (renderer->ratio == 1) {
		renderer->core->setVideoBuffer(renderer->core, surface->pixels, surface->pitch / BYTES_PER_PIXEL);
	} else {
#ifdef USE_PIXMAN
		renderer->outputBuffer = malloc(width * height * BYTES_PER_PIXEL);
		renderer->core->setVideoBuffer(renderer->core, renderer->outputBuffer, width);
#ifdef COLOR_16_BIT
#ifdef COLOR_5_6_5
		pixman_format_code_t format = PIXMAN_r5g6b5;
#else
		pixman_format_code_t format = PIXMAN_x1b5g5r5;
#endif
#else
		pixman_format_code_t format = PIXMAN_x8b8g8r8;
#endif
		renderer->pix = pixman_image_create_bits(format, width, height,
		    renderer->outputBuffer, width * BYTES_PER_PIXEL);
		renderer->screenpix = pixman_image_create_bits(format, renderer->viewportWidth, renderer->viewportHeight, surface->pixels, surface->pitch);

		pixman_transform_t transform;
		pixman_transform_init_identity(&transform);
		pixman_transform_scale(0, &transform, pixman_int_to_fixed(renderer->ratio), pixman_int_to_fixed(renderer->ratio));
		pixman_image_set_transform(renderer->pix, &transform);
		pixman_image_set_filter(renderer->pix, PIXMAN_FILTER_NEAREST, 0, 0);
#else
		return false;
#endif
	}
#endif

	return true;
}
Exemplo n.º 18
0
/*
 * We want to detect the case where we add the same value to a long
 * span of pixels.  The triangles on the end are filled in while we
 * count how many sub-pixel scanlines contribute to the middle section.
 *
 *                 +--------------------------+
 *  fill_height =|   \                      /
 *                     +------------------+
 *                      |================|
 *                   fill_start       fill_end
 */
static void
rasterize_edges_8 (pixman_image_t *image,
                   pixman_edge_t * l,
                   pixman_edge_t * r,
                   pixman_fixed_t  t,
                   pixman_fixed_t  b)
{
    pixman_fixed_t y = t;
    uint32_t  *line;
    int fill_start = -1, fill_end = -1;
    int fill_size = 0;
    uint32_t *buf = (image)->bits.bits;
    int stride = (image)->bits.rowstride;
    int width = (image)->bits.width;

    line = buf + pixman_fixed_to_int (y) * stride;

    for (;;)
    {
        uint8_t *ap = (uint8_t *) line;
        pixman_fixed_t lx, rx;
        int lxi, rxi;

        /* clip X */
        lx = l->x;
        if (lx < 0)
	    lx = 0;

        rx = r->x;

        if (pixman_fixed_to_int (rx) >= width)
	{
	    /* Use the last pixel of the scanline, covered 100%.
	     * We can't use the first pixel following the scanline,
	     * because accessing it could result in a buffer overrun.
	     */
	    rx = pixman_int_to_fixed (width) - 1;
	}

        /* Skip empty (or backwards) sections */
        if (rx > lx)
        {
            int lxs, rxs;

            /* Find pixel bounds for span. */
            lxi = pixman_fixed_to_int (lx);
            rxi = pixman_fixed_to_int (rx);

            /* Sample coverage for edge pixels */
            lxs = RENDER_SAMPLES_X (lx, 8);
            rxs = RENDER_SAMPLES_X (rx, 8);

            /* Add coverage across row */
            if (lxi == rxi)
            {
                WRITE (image, ap + lxi,
		       clip255 (READ (image, ap + lxi) + rxs - lxs));
	    }
            else
            {
                WRITE (image, ap + lxi,
		       clip255 (READ (image, ap + lxi) + N_X_FRAC (8) - lxs));

                /* Move forward so that lxi/rxi is the pixel span */
                lxi++;

                /* Don't bother trying to optimize the fill unless
		 * the span is longer than 4 pixels. */
                if (rxi - lxi > 4)
                {
                    if (fill_start < 0)
                    {
                        fill_start = lxi;
                        fill_end = rxi;
                        fill_size++;
		    }
                    else
                    {
                        if (lxi >= fill_end || rxi < fill_start)
                        {
                            /* We're beyond what we saved, just fill it */
                            ADD_SATURATE_8 (ap + fill_start,
                                            fill_size * N_X_FRAC (8),
                                            fill_end - fill_start);
                            fill_start = lxi;
                            fill_end = rxi;
                            fill_size = 1;
			}
                        else
                        {
                            /* Update fill_start */
                            if (lxi > fill_start)
                            {
                                ADD_SATURATE_8 (ap + fill_start,
                                                fill_size * N_X_FRAC (8),
                                                lxi - fill_start);
                                fill_start = lxi;
			    }
                            else if (lxi < fill_start)
                            {
                                ADD_SATURATE_8 (ap + lxi, N_X_FRAC (8),
                                                fill_start - lxi);
			    }

                            /* Update fill_end */
                            if (rxi < fill_end)
                            {
                                ADD_SATURATE_8 (ap + rxi,
                                                fill_size * N_X_FRAC (8),
                                                fill_end - rxi);
                                fill_end = rxi;
			    }
                            else if (fill_end < rxi)
                            {
                                ADD_SATURATE_8 (ap + fill_end,
                                                N_X_FRAC (8),
                                                rxi - fill_end);
			    }
                            fill_size++;
			}
		    }
		}
                else
                {
                    ADD_SATURATE_8 (ap + lxi, N_X_FRAC (8), rxi - lxi);
		}

                WRITE (image, ap + rxi, clip255 (READ (image, ap + rxi) + rxs));
	    }
	}

        if (y == b)
        {
            /* We're done, make sure we clean up any remaining fill. */
            if (fill_start != fill_end)
            {
                if (fill_size == N_Y_FRAC (8))
                {
                    MEMSET_WRAPPED (image, ap + fill_start,
				    0xff, fill_end - fill_start);
		}
                else
                {
                    ADD_SATURATE_8 (ap + fill_start, fill_size * N_X_FRAC (8),
                                    fill_end - fill_start);
		}
	    }
            break;
	}

        if (pixman_fixed_frac (y) != Y_FRAC_LAST (8))
        {
            RENDER_EDGE_STEP_SMALL (l);
            RENDER_EDGE_STEP_SMALL (r);
            y += STEP_Y_SMALL (8);
	}
        else
        {
            RENDER_EDGE_STEP_BIG (l);
            RENDER_EDGE_STEP_BIG (r);
            y += STEP_Y_BIG (8);
            if (fill_start != fill_end)
            {
                if (fill_size == N_Y_FRAC (8))
                {
                    MEMSET_WRAPPED (image, ap + fill_start,
				    0xff, fill_end - fill_start);
		}
                else
                {
                    ADD_SATURATE_8 (ap + fill_start, fill_size * N_X_FRAC (8),
                                    fill_end - fill_start);
		}
		
                fill_start = fill_end = -1;
                fill_size = 0;
	    }
	    
            line += stride;
	}
    }
}
Exemplo n.º 19
0
static uint32_t *
conical_get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask)
{
    pixman_image_t *image = iter->image;
    int x = iter->x;
    int y = iter->y;
    int width = iter->width;
    uint32_t *buffer = iter->buffer;

    gradient_t *gradient = (gradient_t *)image;
    conical_gradient_t *conical = (conical_gradient_t *)image;
    uint32_t       *end = buffer + width;
    pixman_gradient_walker_t walker;
    pixman_bool_t affine = TRUE;
    double cx = 1.;
    double cy = 0.;
    double cz = 0.;
    double rx = x + 0.5;
    double ry = y + 0.5;
    double rz = 1.;

    _pixman_gradient_walker_init (&walker, gradient, image->common.repeat);

    if (image->common.transform)
    {
        pixman_vector_t v;

        /* reference point is the center of the pixel */
        v.vector[0] = pixman_int_to_fixed (x) + pixman_fixed_1 / 2;
        v.vector[1] = pixman_int_to_fixed (y) + pixman_fixed_1 / 2;
        v.vector[2] = pixman_fixed_1;

        if (!pixman_transform_point_3d (image->common.transform, &v))
            return iter->buffer;

        cx = image->common.transform->matrix[0][0] / 65536.;
        cy = image->common.transform->matrix[1][0] / 65536.;
        cz = image->common.transform->matrix[2][0] / 65536.;

        rx = v.vector[0] / 65536.;
        ry = v.vector[1] / 65536.;
        rz = v.vector[2] / 65536.;

        affine =
            image->common.transform->matrix[2][0] == 0 &&
            v.vector[2] == pixman_fixed_1;
    }

    if (affine)
    {
        rx -= conical->center.x / 65536.;
        ry -= conical->center.y / 65536.;

        while (buffer < end)
        {
            if (!mask || *mask++)
            {
                double t = coordinates_to_parameter (rx, ry, conical->angle);

                *buffer = _pixman_gradient_walker_pixel (
                              &walker, (pixman_fixed_48_16_t)pixman_double_to_fixed (t));
            }

            ++buffer;

            rx += cx;
            ry += cy;
        }
    }
    else
    {
        while (buffer < end)
        {
            double x, y;

            if (!mask || *mask++)
            {
                double t;

                if (rz != 0)
                {
                    x = rx / rz;
                    y = ry / rz;
                }
                else
                {
                    x = y = 0.;
                }

                x -= conical->center.x / 65536.;
                y -= conical->center.y / 65536.;

                t = coordinates_to_parameter (x, y, conical->angle);

                *buffer = _pixman_gradient_walker_pixel (
                              &walker, (pixman_fixed_48_16_t)pixman_double_to_fixed (t));
            }

            ++buffer;

            rx += cx;
            ry += cy;
            rz += cz;
        }
    }

    iter->y++;
    return iter->buffer;
}
Exemplo n.º 20
0
static uint32_t *
linear_get_scanline_narrow (pixman_iter_t  *iter,
			    const uint32_t *mask)
{
    pixman_image_t *image  = iter->image;
    int             x      = iter->x;
    int             y      = iter->y;
    int             width  = iter->width;
    uint32_t *      buffer = iter->buffer;

    pixman_vector_t v, unit;
    pixman_fixed_32_32_t l;
    pixman_fixed_48_16_t dx, dy;
    gradient_t *gradient = (gradient_t *)image;
    linear_gradient_t *linear = (linear_gradient_t *)image;
    uint32_t *end = buffer + width;
    pixman_gradient_walker_t walker;

    _pixman_gradient_walker_init (&walker, gradient, image->common.repeat);

    /* reference point is the center of the pixel */
    v.vector[0] = pixman_int_to_fixed (x) + pixman_fixed_1 / 2;
    v.vector[1] = pixman_int_to_fixed (y) + pixman_fixed_1 / 2;
    v.vector[2] = pixman_fixed_1;

    if (image->common.transform)
    {
	if (!pixman_transform_point_3d (image->common.transform, &v))
	    return iter->buffer;

	unit.vector[0] = image->common.transform->matrix[0][0];
	unit.vector[1] = image->common.transform->matrix[1][0];
	unit.vector[2] = image->common.transform->matrix[2][0];
    }
    else
    {
	unit.vector[0] = pixman_fixed_1;
	unit.vector[1] = 0;
	unit.vector[2] = 0;
    }

    dx = linear->p2.x - linear->p1.x;
    dy = linear->p2.y - linear->p1.y;

    l = dx * dx + dy * dy;

    if (l == 0 || unit.vector[2] == 0)
    {
	/* affine transformation only */
        pixman_fixed_32_32_t t, next_inc;
	double inc;

	if (l == 0 || v.vector[2] == 0)
	{
	    t = 0;
	    inc = 0;
	}
	else
	{
	    double invden, v2;

	    invden = pixman_fixed_1 * (double) pixman_fixed_1 /
		(l * (double) v.vector[2]);
	    v2 = v.vector[2] * (1. / pixman_fixed_1);
	    t = ((dx * v.vector[0] + dy * v.vector[1]) - 
		 (dx * linear->p1.x + dy * linear->p1.y) * v2) * invden;
	    inc = (dx * unit.vector[0] + dy * unit.vector[1]) * invden;
	}
	next_inc = 0;

	if (((pixman_fixed_32_32_t )(inc * width)) == 0)
	{
	    register uint32_t color;

	    color = _pixman_gradient_walker_pixel (&walker, t);
	    while (buffer < end)
		*buffer++ = color;
	}
	else
	{
	    int i;

	    i = 0;
	    while (buffer < end)
	    {
		if (!mask || *mask++)
		{
		    *buffer = _pixman_gradient_walker_pixel (&walker,
							     t + next_inc);
		}
		i++;
		next_inc = inc * i;
		buffer++;
	    }
	}
    }
    else
    {
	/* projective transformation */
        double t;

	t = 0;

	while (buffer < end)
	{
	    if (!mask || *mask++)
	    {
	        if (v.vector[2] != 0)
		{
		    double invden, v2;

		    invden = pixman_fixed_1 * (double) pixman_fixed_1 /
			(l * (double) v.vector[2]);
		    v2 = v.vector[2] * (1. / pixman_fixed_1);
		    t = ((dx * v.vector[0] + dy * v.vector[1]) - 
			 (dx * linear->p1.x + dy * linear->p1.y) * v2) * invden;
		}

		*buffer = _pixman_gradient_walker_pixel (&walker, t);
	    }

	    ++buffer;

	    v.vector[0] += unit.vector[0];
	    v.vector[1] += unit.vector[1];
	    v.vector[2] += unit.vector[2];
	}
    }

    iter->y++;

    return iter->buffer;
}
Exemplo n.º 21
0
static void
set_image_properties(pixman_image_t * image, PicturePtr pict, Bool has_clip,
                     int *xoff, int *yoff, Bool is_alpha_map)
{
    pixman_repeat_t repeat;
    pixman_filter_t filter;

    if (pict->transform) {
        /* For source images, adjust the transform to account
         * for the drawable offset within the pixman image,
         * then set the offset to 0 as it will be used
         * to compute positions within the transformed image.
         */
        if (!has_clip) {
            struct pixman_transform adjusted;

            adjusted = *pict->transform;
            pixman_transform_translate(&adjusted,
                                       NULL,
                                       pixman_int_to_fixed(*xoff),
                                       pixman_int_to_fixed(*yoff));
            pixman_image_set_transform(image, &adjusted);
            *xoff = 0;
            *yoff = 0;
        }
        else
            pixman_image_set_transform(image, pict->transform);
    }

    switch (pict->repeatType) {
    default:
    case RepeatNone:
        repeat = PIXMAN_REPEAT_NONE;
        break;

    case RepeatPad:
        repeat = PIXMAN_REPEAT_PAD;
        break;

    case RepeatNormal:
        repeat = PIXMAN_REPEAT_NORMAL;
        break;

    case RepeatReflect:
        repeat = PIXMAN_REPEAT_REFLECT;
        break;
    }

    pixman_image_set_repeat(image, repeat);

    /* Fetch alpha map unless 'pict' is being used
     * as the alpha map for this operation
     */
    if (pict->alphaMap && !is_alpha_map) {
        int alpha_xoff, alpha_yoff;
        pixman_image_t *alpha_map =
            image_from_pict_internal(pict->alphaMap, FALSE, &alpha_xoff,
                                     &alpha_yoff, TRUE);

        pixman_image_set_alpha_map(image, alpha_map, pict->alphaOrigin.x,
                                   pict->alphaOrigin.y);

        free_pixman_pict(pict->alphaMap, alpha_map);
    }

    pixman_image_set_component_alpha(image, pict->componentAlpha);

    switch (pict->filter) {
    default:
    case PictFilterNearest:
    case PictFilterFast:
        filter = PIXMAN_FILTER_NEAREST;
        break;

    case PictFilterBilinear:
    case PictFilterGood:
        filter = PIXMAN_FILTER_BILINEAR;
        break;

    case PictFilterConvolution:
        filter = PIXMAN_FILTER_CONVOLUTION;
        break;
    }

    if (pict->pDrawable)
        pixman_image_set_destroy_function(image, &image_destroy,
                                          pict->pDrawable);

    pixman_image_set_filter(image, filter,
                            (pixman_fixed_t *) pict->filter_params,
                            pict->filter_nparams);
    pixman_image_set_source_clipping(image, TRUE);
}
Exemplo n.º 22
0
void
_pixman_general_radial_gradient_get_scanline_32 (pixman_image_t *image,
						 int             x,
						 int             y,
						 int             width,
						 uint32_t *      buffer,
						 const uint32_t *mask,
						 uint32_t        mask_bits)
{
    /*
     * In the radial gradient problem we are given two circles (c₁,r₁) and
     * (c₂,r₂) that define the gradient itself. Then, for any point p, we
     * must compute the value(s) of t within [0.0, 1.0] representing the
     * circle(s) that would color the point.
     *
     * There are potentially two values of t since the point p can be
     * colored by both sides of the circle, (which happens whenever one
     * circle is not entirely contained within the other).
     *
     * If we solve for a value of t that is outside of [0.0, 1.0] then we
     * use the extend mode (NONE, REPEAT, REFLECT, or PAD) to map to a
     * value within [0.0, 1.0].
     *
     * Here is an illustration of the problem:
     *
     *              p₂
     *           p  •
     *           •   ╲
     *        ·       ╲r₂
     *  p₁ ·           ╲
     *  •              θ╲
     *   ╲             ╌╌•
     *    ╲r₁        ·   c₂
     *    θ╲    ·
     *    ╌╌•
     *      c₁
     *
     * Given (c₁,r₁), (c₂,r₂) and p, we must find an angle θ such that two
     * points p₁ and p₂ on the two circles are collinear with p. Then, the
     * desired value of t is the ratio of the length of p₁p to the length
     * of p₁p₂.
     *
     * So, we have six unknown values: (p₁x, p₁y), (p₂x, p₂y), θ and t.
     * We can also write six equations that constrain the problem:
     *
     * Point p₁ is a distance r₁ from c₁ at an angle of θ:
     *
     *	1. p₁x = c₁x + r₁·cos θ
     *	2. p₁y = c₁y + r₁·sin θ
     *
     * Point p₂ is a distance r₂ from c₂ at an angle of θ:
     *
     *	3. p₂x = c₂x + r2·cos θ
     *	4. p₂y = c₂y + r2·sin θ
     *
     * Point p lies at a fraction t along the line segment p₁p₂:
     *
     *	5. px = t·p₂x + (1-t)·p₁x
     *	6. py = t·p₂y + (1-t)·p₁y
     *
     * To solve, first subtitute 1-4 into 5 and 6:
     *
     * px = t·(c₂x + r₂·cos θ) + (1-t)·(c₁x + r₁·cos θ)
     * py = t·(c₂y + r₂·sin θ) + (1-t)·(c₁y + r₁·sin θ)
     *
     * Then solve each for cos θ and sin θ expressed as a function of t:
     *
     * cos θ = (-(c₂x - c₁x)·t + (px - c₁x)) / ((r₂-r₁)·t + r₁)
     * sin θ = (-(c₂y - c₁y)·t + (py - c₁y)) / ((r₂-r₁)·t + r₁)
     *
     * To simplify this a bit, we define new variables for several of the
     * common terms as shown below:
     *
     *              p₂
     *           p  •
     *           •   ╲
     *        ·  ┆    ╲r₂
     *  p₁ ·     ┆     ╲
     *  •     pdy┆      ╲
     *   ╲       ┆       •c₂
     *    ╲r₁    ┆   ·   ┆
     *     ╲    ·┆       ┆cdy
     *      •╌╌╌╌┴╌╌╌╌╌╌╌┘
     *    c₁  pdx   cdx
     *
     * cdx = (c₂x - c₁x)
     * cdy = (c₂y - c₁y)
     *  dr =  r₂-r₁
     * pdx =  px - c₁x
     * pdy =  py - c₁y
     *
     * Note that cdx, cdy, and dr do not depend on point p at all, so can
     * be pre-computed for the entire gradient. The simplifed equations
     * are now:
     *
     * cos θ = (-cdx·t + pdx) / (dr·t + r₁)
     * sin θ = (-cdy·t + pdy) / (dr·t + r₁)
     *
     * Finally, to get a single function of t and eliminate the last
     * unknown θ, we use the identity sin²θ + cos²θ = 1. First, square
     * each equation, (we knew a quadratic was coming since it must be
     * possible to obtain two solutions in some cases):
     *
     * cos²θ = (cdx²t² - 2·cdx·pdx·t + pdx²) / (dr²·t² + 2·r₁·dr·t + r₁²)
     * sin²θ = (cdy²t² - 2·cdy·pdy·t + pdy²) / (dr²·t² + 2·r₁·dr·t + r₁²)
     *
     * Then add both together, set the result equal to 1, and express as a
     * standard quadratic equation in t of the form At² + Bt + C = 0
     *
     * (cdx² + cdy² - dr²)·t² - 2·(cdx·pdx + cdy·pdy + r₁·dr)·t + (pdx² + pdy² - r₁²) = 0
     *
     * In other words:
     *
     * A = cdx² + cdy² - dr²
     * B = -2·(pdx·cdx + pdy·cdy + r₁·dr)
     * C = pdx² + pdy² - r₁²
     *
     * And again, notice that A does not depend on p, so can be
     * precomputed. From here we just use the quadratic formula to solve
     * for t:
     *
     * t = (-2·B ± ⎷(B² - 4·A·C)) / 2·A
     */

    gradient_t *gradient = (gradient_t *)image;
    source_image_t *source = (source_image_t *)image;
    radial_gradient_t *radial = (radial_gradient_t *)image;
    uint32_t *end = buffer + width;
    pixman_gradient_walker_t walker;
    pixman_bool_t affine = TRUE;
    double cx = 1.;
    double cy = 0.;
    double cz = 0.;
    double rx = x + 0.5;
    double ry = y + 0.5;
    double rz = 1.;

    _pixman_gradient_walker_init (&walker, gradient, source->common.repeat);

    if (source->common.transform)
    {
	pixman_vector_t v;
	/* reference point is the center of the pixel */
	v.vector[0] = pixman_int_to_fixed (x) + pixman_fixed_1 / 2;
	v.vector[1] = pixman_int_to_fixed (y) + pixman_fixed_1 / 2;
	v.vector[2] = pixman_fixed_1;
	
	if (!pixman_transform_point_3d (source->common.transform, &v))
	    return;

	cx = source->common.transform->matrix[0][0] / 65536.;
	cy = source->common.transform->matrix[1][0] / 65536.;
	cz = source->common.transform->matrix[2][0] / 65536.;
	
	rx = v.vector[0] / 65536.;
	ry = v.vector[1] / 65536.;
	rz = v.vector[2] / 65536.;

	affine =
	    source->common.transform->matrix[2][0] == 0 &&
	    v.vector[2] == pixman_fixed_1;
    }

    if (affine)
    {
	/* When computing t over a scanline, we notice that some expressions
	 * are constant so we can compute them just once. Given:
	 *
	 * t = (-2·B ± ⎷(B² - 4·A·C)) / 2·A
	 *
	 * where
	 *
	 * A = cdx² + cdy² - dr² [precomputed as radial->A]
	 * B = -2·(pdx·cdx + pdy·cdy + r₁·dr)
	 * C = pdx² + pdy² - r₁²
	 *
	 * Since we have an affine transformation, we know that (pdx, pdy)
	 * increase linearly with each pixel,
	 *
	 * pdx = pdx₀ + n·cx,
	 * pdy = pdy₀ + n·cy,
	 *
	 * we can then express B in terms of an linear increment along
	 * the scanline:
	 *
	 * B = B₀ + n·cB, with
	 * B₀ = -2·(pdx₀·cdx + pdy₀·cdy + r₁·dr) and
	 * cB = -2·(cx·cdx + cy·cdy)
	 *
	 * Thus we can replace the full evaluation of B per-pixel (4 multiplies,
	 * 2 additions) with a single addition.
	 */
	float r1   = radial->c1.radius / 65536.;
	float r1sq = r1 * r1;
	float pdx  = rx - radial->c1.x / 65536.;
	float pdy  = ry - radial->c1.y / 65536.;
	float A = radial->A;
	float invA = -65536. / (2. * A);
	float A4 = -4. * A;
	float B  = -2. * (pdx*radial->cdx + pdy*radial->cdy + r1*radial->dr);
	float cB = -2. *  (cx*radial->cdx +  cy*radial->cdy);
	pixman_bool_t invert = A * radial->dr < 0;

	while (buffer < end)
	{
	    if (!mask || *mask++ & mask_bits)
	    {
		pixman_fixed_t t;
		double det = B * B + A4 * (pdx * pdx + pdy * pdy - r1sq);
		if (det <= 0.)
		    t = (pixman_fixed_t) (B * invA);
		else if (invert)
		    t = (pixman_fixed_t) ((B + sqrt (det)) * invA);
		else
		    t = (pixman_fixed_t) ((B - sqrt (det)) * invA);

		*buffer = _pixman_gradient_walker_pixel (&walker, t);
	    }
	    ++buffer;

	    pdx += cx;
	    pdy += cy;
	    B += cB;
	}
    }
    else
    {
	/* projective */
	while (buffer < end)
	{
	    if (!mask || *mask++ & mask_bits)
	    {
		double pdx, pdy;
		double B, C;
		double det;
		double c1x = radial->c1.x / 65536.0;
		double c1y = radial->c1.y / 65536.0;
		double r1  = radial->c1.radius / 65536.0;
		pixman_fixed_48_16_t t;
		double x, y;

		if (rz != 0)
		{
		    x = rx / rz;
		    y = ry / rz;
		}
		else
		{
		    x = y = 0.;
		}

		pdx = x - c1x;
		pdy = y - c1y;

		B = -2 * (pdx * radial->cdx +
			  pdy * radial->cdy +
			  r1 * radial->dr);
		C = (pdx * pdx + pdy * pdy - r1 * r1);

		det = (B * B) - (4 * radial->A * C);
		if (det < 0.0)
		    det = 0.0;

		if (radial->A * radial->dr < 0)
		    t = (pixman_fixed_48_16_t) ((-B - sqrt (det)) / (2.0 * radial->A) * 65536);
		else
		    t = (pixman_fixed_48_16_t) ((-B + sqrt (det)) / (2.0 * radial->A) * 65536);

		*buffer = _pixman_gradient_walker_pixel (&walker, t);
	    }
	    
	    ++buffer;

	    rx += cx;
	    ry += cy;
	    rz += cz;
	}
    }
}
Exemplo n.º 23
0
int
main (int argc, char **argv)
{
#define WIDTH 400
#define HEIGHT 200
    
    uint32_t *alpha = malloc (WIDTH * HEIGHT * 4);
    uint32_t *dest = malloc (WIDTH * HEIGHT * 4);
    uint32_t *src = malloc (WIDTH * HEIGHT * 4);
    pixman_image_t *grad_img;
    pixman_image_t *alpha_img;
    pixman_image_t *dest_img;
    pixman_image_t *src_img;
    int i;
    pixman_gradient_stop_t stops[2] =
	{
	    { pixman_int_to_fixed (0), { 0x0000, 0x0000, 0x0000, 0x0000 } },
	    { pixman_int_to_fixed (1), { 0xffff, 0x0000, 0x1111, 0xffff } }
	};
    pixman_point_fixed_t p1 = { pixman_double_to_fixed (0), 0 };
    pixman_point_fixed_t p2 = { pixman_double_to_fixed (WIDTH),
				pixman_int_to_fixed (0) };
#if 0
    pixman_transform_t trans = {
	{ { pixman_double_to_fixed (2), pixman_double_to_fixed (0.5), pixman_double_to_fixed (-100), },
	  { pixman_double_to_fixed (0), pixman_double_to_fixed (3), pixman_double_to_fixed (0), },
	  { pixman_double_to_fixed (0), pixman_double_to_fixed (0.000), pixman_double_to_fixed (1.0) } 
	}
    };
#else
    pixman_transform_t trans = {
	{ { pixman_fixed_1, 0, 0 },
	  { 0, pixman_fixed_1, 0 },
	  { 0, 0, pixman_fixed_1 } }
    };
#endif

    pixman_point_fixed_t c_inner;
    pixman_point_fixed_t c_outer;
    pixman_fixed_t r_inner;
    pixman_fixed_t r_outer;
    
    for (i = 0; i < WIDTH * HEIGHT; ++i)
	alpha[i] = 0x4f00004f; /* pale blue */
    
    alpha_img = pixman_image_create_bits (PIXMAN_a8r8g8b8,
					 WIDTH, HEIGHT, 
					  alpha,
					 WIDTH * 4);

    for (i = 0; i < WIDTH * HEIGHT; ++i)
	dest[i] = 0xffffff00;		/* yellow */
    
    dest_img = pixman_image_create_bits (PIXMAN_a8r8g8b8,
					 WIDTH, HEIGHT, 
					 dest,
					 WIDTH * 4);

    for (i = 0; i < WIDTH * HEIGHT; ++i)
	src[i] = 0xffff0000;

    src_img = pixman_image_create_bits (PIXMAN_a8r8g8b8,
					WIDTH, HEIGHT,
					src,
					WIDTH * 4);
    
    c_inner.x = pixman_double_to_fixed (50.0);
    c_inner.y = pixman_double_to_fixed (50.0);
    c_outer.x = pixman_double_to_fixed (50.0);
    c_outer.y = pixman_double_to_fixed (50.0);
    r_inner = 0;
    r_outer = pixman_double_to_fixed (50.0);
    
#if 0
    grad_img = pixman_image_create_conical_gradient (&c_inner, r_inner,
						    stops, 2);
#endif
#if 0
    grad_img = pixman_image_create_conical_gradient (&c_inner, r_inner,
						    stops, 2);
    grad_img = pixman_image_create_linear_gradient (&c_inner, &c_outer,
						   r_inner, r_outer,
						   stops, 2);
#endif
    
    grad_img = pixman_image_create_linear_gradient  (&p1, &p2,
						    stops, 2);

    pixman_image_set_transform (grad_img, &trans);
    pixman_image_set_repeat (grad_img, PIXMAN_REPEAT_PAD);
    
    pixman_image_composite (PIXMAN_OP_OVER, grad_img, NULL, alpha_img,
			    0, 0, 0, 0, 0, 0, 10 * WIDTH, HEIGHT);

    pixman_image_set_alpha_map (src_img, alpha_img, 10, 10);
    
    pixman_image_composite (PIXMAN_OP_OVER, src_img, NULL, dest_img,
			    0, 0, 0, 0, 0, 0, 10 * WIDTH, HEIGHT);
    
    printf ("0, 0: %x\n", dest[0]);
    printf ("10, 10: %x\n", dest[10 * 10 + 10]);
    printf ("w, h: %x\n", dest[(HEIGHT - 1) * 100 + (WIDTH - 1)]);
    
    show_image (dest_img);

    pixman_image_unref (src_img);
    pixman_image_unref (grad_img);
    pixman_image_unref (alpha_img);
    free (dest);
    
    return 0;
}
Exemplo n.º 24
0
static force_inline void
bits_image_fetch_nearest_affine (pixman_image_t * image,
				 int              offset,
				 int              line,
				 int              width,
				 uint32_t *       buffer,
				 const uint32_t * mask,
				 
				 convert_pixel_t	convert_pixel,
				 pixman_format_code_t	format,
				 pixman_repeat_t	repeat_mode)
{
    pixman_fixed_t x, y;
    pixman_fixed_t ux, uy;
    pixman_vector_t v;
    bits_image_t *bits = &image->bits;
    int i;

    /* reference point is the center of the pixel */
    v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
    v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
    v.vector[2] = pixman_fixed_1;

    if (!pixman_transform_point_3d (image->common.transform, &v))
	return;

    ux = image->common.transform->matrix[0][0];
    uy = image->common.transform->matrix[1][0];

    x = v.vector[0];
    y = v.vector[1];

    for (i = 0; i < width; ++i)
    {
	int width, height, x0, y0;
	const uint8_t *row;

	if (mask && !mask[i])
	    goto next;
	
	width = image->bits.width;
	height = image->bits.height;
	x0 = pixman_fixed_to_int (x - pixman_fixed_e);
	y0 = pixman_fixed_to_int (y - pixman_fixed_e);

	if (repeat_mode == PIXMAN_REPEAT_NONE &&
	    (y0 < 0 || y0 >= height || x0 < 0 || x0 >= width))
	{
	    buffer[i] = 0;
	}
	else
	{
	    uint32_t mask = PIXMAN_FORMAT_A (format)? 0 : 0xff000000;

	    if (repeat_mode != PIXMAN_REPEAT_NONE)
	    {
		repeat (repeat_mode, &x0, width);
		repeat (repeat_mode, &y0, height);
	    }

	    row = (uint8_t *)bits->bits + bits->rowstride * 4 * y0;

	    buffer[i] = convert_pixel (row, x0) | mask;
	}

    next:
	x += ux;
	y += uy;
    }
}
Exemplo n.º 25
0
static force_inline void
bits_image_fetch_bilinear_affine (pixman_image_t * image,
				  int              offset,
				  int              line,
				  int              width,
				  uint32_t *       buffer,
				  const uint32_t * mask,

				  convert_pixel_t	convert_pixel,
				  pixman_format_code_t	format,
				  pixman_repeat_t	repeat_mode)
{
    pixman_fixed_t x, y;
    pixman_fixed_t ux, uy;
    pixman_vector_t v;
    bits_image_t *bits = &image->bits;
    int i;

    /* reference point is the center of the pixel */
    v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
    v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
    v.vector[2] = pixman_fixed_1;

    if (!pixman_transform_point_3d (image->common.transform, &v))
	return;

    ux = image->common.transform->matrix[0][0];
    uy = image->common.transform->matrix[1][0];

    x = v.vector[0];
    y = v.vector[1];

    for (i = 0; i < width; ++i)
    {
	int x1, y1, x2, y2;
	uint32_t tl, tr, bl, br;
	int32_t distx, disty;
	int width = image->bits.width;
	int height = image->bits.height;
	const uint8_t *row1;
	const uint8_t *row2;

	if (mask && !mask[i])
	    goto next;

	x1 = x - pixman_fixed_1 / 2;
	y1 = y - pixman_fixed_1 / 2;

	distx = pixman_fixed_to_bilinear_weight (x1);
	disty = pixman_fixed_to_bilinear_weight (y1);

	y1 = pixman_fixed_to_int (y1);
	y2 = y1 + 1;
	x1 = pixman_fixed_to_int (x1);
	x2 = x1 + 1;

	if (repeat_mode != PIXMAN_REPEAT_NONE)
	{
	    uint32_t mask;

	    mask = PIXMAN_FORMAT_A (format)? 0 : 0xff000000;

	    repeat (repeat_mode, &x1, width);
	    repeat (repeat_mode, &y1, height);
	    repeat (repeat_mode, &x2, width);
	    repeat (repeat_mode, &y2, height);

	    row1 = (uint8_t *)bits->bits + bits->rowstride * 4 * y1;
	    row2 = (uint8_t *)bits->bits + bits->rowstride * 4 * y2;

	    tl = convert_pixel (row1, x1) | mask;
	    tr = convert_pixel (row1, x2) | mask;
	    bl = convert_pixel (row2, x1) | mask;
	    br = convert_pixel (row2, x2) | mask;
	}
	else
	{
	    uint32_t mask1, mask2;
	    int bpp;

	    /* Note: PIXMAN_FORMAT_BPP() returns an unsigned value,
	     * which means if you use it in expressions, those
	     * expressions become unsigned themselves. Since
	     * the variables below can be negative in some cases,
	     * that will lead to crashes on 64 bit architectures.
	     *
	     * So this line makes sure bpp is signed
	     */
	    bpp = PIXMAN_FORMAT_BPP (format);

	    if (x1 >= width || x2 < 0 || y1 >= height || y2 < 0)
	    {
		buffer[i] = 0;
		goto next;
	    }

	    if (y2 == 0)
	    {
		row1 = zero;
		mask1 = 0;
	    }
	    else
	    {
		row1 = (uint8_t *)bits->bits + bits->rowstride * 4 * y1;
		row1 += bpp / 8 * x1;

		mask1 = PIXMAN_FORMAT_A (format)? 0 : 0xff000000;
	    }

	    if (y1 == height - 1)
	    {
		row2 = zero;
		mask2 = 0;
	    }
	    else
	    {
		row2 = (uint8_t *)bits->bits + bits->rowstride * 4 * y2;
		row2 += bpp / 8 * x1;

		mask2 = PIXMAN_FORMAT_A (format)? 0 : 0xff000000;
	    }

	    if (x2 == 0)
	    {
		tl = 0;
		bl = 0;
	    }
	    else
	    {
		tl = convert_pixel (row1, 0) | mask1;
		bl = convert_pixel (row2, 0) | mask2;
	    }

	    if (x1 == width - 1)
	    {
		tr = 0;
		br = 0;
	    }
	    else
	    {
		tr = convert_pixel (row1, 1) | mask1;
		br = convert_pixel (row2, 1) | mask2;
	    }
	}

	buffer[i] = bilinear_interpolation (
	    tl, tr, bl, br, distx, disty);

    next:
	x += ux;
	y += uy;
    }
}
Exemplo n.º 26
0
static uint32_t *
bits_image_fetch_general (pixman_iter_t  *iter,
			  const uint32_t *mask)
{
    pixman_image_t *image  = iter->image;
    int             offset = iter->x;
    int             line   = iter->y++;
    int             width  = iter->width;
    uint32_t *      buffer = iter->buffer;

    pixman_fixed_t x, y, w;
    pixman_fixed_t ux, uy, uw;
    pixman_vector_t v;
    int i;

    /* reference point is the center of the pixel */
    v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
    v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
    v.vector[2] = pixman_fixed_1;

    if (image->common.transform)
    {
	if (!pixman_transform_point_3d (image->common.transform, &v))
	    return buffer;

	ux = image->common.transform->matrix[0][0];
	uy = image->common.transform->matrix[1][0];
	uw = image->common.transform->matrix[2][0];
    }
    else
    {
	ux = pixman_fixed_1;
	uy = 0;
	uw = 0;
    }

    x = v.vector[0];
    y = v.vector[1];
    w = v.vector[2];

    for (i = 0; i < width; ++i)
    {
	pixman_fixed_t x0, y0;

	if (!mask || mask[i])
	{
	    if (w != 0)
	    {
		x0 = ((pixman_fixed_48_16_t)x << 16) / w;
		y0 = ((pixman_fixed_48_16_t)y << 16) / w;
	    }
	    else
	    {
		x0 = 0;
		y0 = 0;
	    }

	    buffer[i] = bits_image_fetch_pixel_filtered (
		&image->bits, x0, y0, fetch_pixel_general);
	}

	x += ux;
	y += uy;
	w += uw;
    }

    return buffer;
}
int
main (int argc, char **argv)
{
#define WIDTH 400
#define HEIGHT 200
    
    uint32_t *dest = malloc (WIDTH * HEIGHT * 4);
    pixman_image_t *src_img;
    pixman_image_t *dest_img;
    int i, j, k, p;

    typedef struct
    {
	pixman_point_fixed_t p0;
	pixman_point_fixed_t p1;
    } point_pair_t;
    
    pixman_gradient_stop_t onestop[1] =
	{
	    { pixman_int_to_fixed (1), { 0xffff, 0xeeee, 0xeeee, 0xeeee } },
	};

    pixman_gradient_stop_t subsetstops[2] =
	{
	    { pixman_int_to_fixed (1), { 0xffff, 0xeeee, 0xeeee, 0xeeee } },
	    { pixman_int_to_fixed (1), { 0xffff, 0xeeee, 0xeeee, 0xeeee } },
	};

    pixman_gradient_stop_t stops01[2] =
	{
	    { pixman_int_to_fixed (0), { 0xffff, 0xeeee, 0xeeee, 0xeeee } },
	    { pixman_int_to_fixed (1), { 0xffff, 0x1111, 0x1111, 0x1111 } }
	};

    point_pair_t point_pairs [] =
	{ { { pixman_double_to_fixed (0), 0 },
	    { pixman_double_to_fixed (WIDTH / 8.), pixman_int_to_fixed (0) } },
	  { { pixman_double_to_fixed (WIDTH / 2.0), pixman_double_to_fixed (HEIGHT / 2.0) },
	    { pixman_double_to_fixed (WIDTH / 2.0), pixman_double_to_fixed (HEIGHT / 2.0) } }
	};
    
    pixman_transform_t transformations[] = {
	{
	    { { pixman_double_to_fixed (2), pixman_double_to_fixed (0.5), pixman_double_to_fixed (-100), },
	      { pixman_double_to_fixed (0), pixman_double_to_fixed (3), pixman_double_to_fixed (0), },
	      { pixman_double_to_fixed (0), pixman_double_to_fixed (0.000), pixman_double_to_fixed (1.0) } 
	    }
	},
	{
	    { { pixman_double_to_fixed (1), pixman_double_to_fixed (0), pixman_double_to_fixed (0), },
	      { pixman_double_to_fixed (0), pixman_double_to_fixed (1), pixman_double_to_fixed (0), },
	      { pixman_double_to_fixed (0), pixman_double_to_fixed (0.000), pixman_double_to_fixed (1.0) } 
	    }
	},
	{
	    { { pixman_double_to_fixed (2), pixman_double_to_fixed (1), pixman_double_to_fixed (0), },
	      { pixman_double_to_fixed (1), pixman_double_to_fixed (1), pixman_double_to_fixed (0), },
	      { pixman_double_to_fixed (2), pixman_double_to_fixed (1.000), pixman_double_to_fixed (1.0) } 
	    }
	},
	{
	    { { pixman_double_to_fixed (2), pixman_double_to_fixed (1), pixman_double_to_fixed (0), },
	      { pixman_double_to_fixed (1), pixman_double_to_fixed (1), pixman_double_to_fixed (0), },
	      { pixman_double_to_fixed (0), pixman_double_to_fixed (0), pixman_double_to_fixed (0) } 
	    }
	},
	{
	    { { pixman_double_to_fixed (2), pixman_double_to_fixed (1), pixman_double_to_fixed (0), },
	      { pixman_double_to_fixed (1), pixman_double_to_fixed (1), pixman_double_to_fixed (0), },
	      { pixman_double_to_fixed (2), pixman_double_to_fixed (-1), pixman_double_to_fixed (0) } 
	    }
	},
	{
	    { { pixman_double_to_fixed (2), pixman_double_to_fixed (1), pixman_double_to_fixed (3), },
	      { pixman_double_to_fixed (1), pixman_double_to_fixed (1), pixman_double_to_fixed (0), },
	      { pixman_double_to_fixed (2), pixman_double_to_fixed (-1), pixman_double_to_fixed (0) } 
	    }
	},
    };
    
    pixman_fixed_t r_inner;
    pixman_fixed_t r_outer;

    enable_divbyzero_exceptions();
    
    for (i = 0; i < WIDTH * HEIGHT; ++i)
	dest[i] = 0x4f00004f; /* pale blue */
    
    dest_img = pixman_image_create_bits (PIXMAN_a8r8g8b8,
					 WIDTH, HEIGHT, 
					 dest,
					 WIDTH * 4);

    r_inner = 0;
    r_outer = pixman_double_to_fixed (50.0);
    
    for (i = 0; i < 3; ++i)
    {
	pixman_gradient_stop_t *stops;
        int num_stops;

	if (i == 0)
	{
	    stops = onestop;
	    num_stops = ARRAY_LENGTH (onestop);
	}
	else if (i == 1)
	{
	    stops = subsetstops;
	    num_stops = ARRAY_LENGTH (subsetstops);
	}
	else
	{
	    stops = stops01;
	    num_stops = ARRAY_LENGTH (stops01);
	}
	
	for (j = 0; j < 3; ++j)
	{
	    for (p = 0; p < ARRAY_LENGTH (point_pairs); ++p)
	    {
		point_pair_t *pair = &(point_pairs[p]);

		if (j == 0)
		    src_img = pixman_image_create_conical_gradient (&(pair->p0), r_inner,
								    stops, num_stops);
		else if (j == 1)
		    src_img = pixman_image_create_radial_gradient  (&(pair->p0), &(pair->p1),
								    r_inner, r_outer,
								    stops, num_stops);
		else
		    src_img = pixman_image_create_linear_gradient  (&(pair->p0), &(pair->p1),
								    stops, num_stops);
		
		for (k = 0; k < ARRAY_LENGTH (transformations); ++k)
		{
		    pixman_image_set_transform (src_img, &transformations[k]);
		    
		    pixman_image_set_repeat (src_img, PIXMAN_REPEAT_NONE);
		    pixman_image_composite (PIXMAN_OP_OVER, src_img, NULL, dest_img,
					    0, 0, 0, 0, 0, 0, 10 * WIDTH, HEIGHT);
		}

		pixman_image_unref (src_img);
	    }

	}
    }

    pixman_image_unref (dest_img);
    free (dest);
    
    return 0;
}
static uint32_t *
radial_get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask)
{
    /*
     * Implementation of radial gradients following the PDF specification.
     * See section 8.7.4.5.4 Type 3 (Radial) Shadings of the PDF Reference
     * Manual (PDF 32000-1:2008 at the time of this writing).
     *
     * In the radial gradient problem we are given two circles (c₁,r₁) and
     * (c₂,r₂) that define the gradient itself.
     *
     * Mathematically the gradient can be defined as the family of circles
     *
     *     ((1-t)·c₁ + t·(c₂), (1-t)·r₁ + t·r₂)
     *
     * excluding those circles whose radius would be < 0. When a point
     * belongs to more than one circle, the one with a bigger t is the only
     * one that contributes to its color. When a point does not belong
     * to any of the circles, it is transparent black, i.e. RGBA (0, 0, 0, 0).
     * Further limitations on the range of values for t are imposed when
     * the gradient is not repeated, namely t must belong to [0,1].
     *
     * The graphical result is the same as drawing the valid (radius > 0)
     * circles with increasing t in [-inf, +inf] (or in [0,1] if the gradient
     * is not repeated) using SOURCE operator composition.
     *
     * It looks like a cone pointing towards the viewer if the ending circle
     * is smaller than the starting one, a cone pointing inside the page if
     * the starting circle is the smaller one and like a cylinder if they
     * have the same radius.
     *
     * What we actually do is, given the point whose color we are interested
     * in, compute the t values for that point, solving for t in:
     *
     *     length((1-t)·c₁ + t·(c₂) - p) = (1-t)·r₁ + t·r₂
     *
     * Let's rewrite it in a simpler way, by defining some auxiliary
     * variables:
     *
     *     cd = c₂ - c₁
     *     pd = p - c₁
     *     dr = r₂ - r₁
     *     length(t·cd - pd) = r₁ + t·dr
     *
     * which actually means
     *
     *     hypot(t·cdx - pdx, t·cdy - pdy) = r₁ + t·dr
     *
     * or
     *
     *     ⎷((t·cdx - pdx)² + (t·cdy - pdy)²) = r₁ + t·dr.
     *
     * If we impose (as stated earlier) that r₁ + t·dr >= 0, it becomes:
     *
     *     (t·cdx - pdx)² + (t·cdy - pdy)² = (r₁ + t·dr)²
     *
     * where we can actually expand the squares and solve for t:
     *
     *     t²cdx² - 2t·cdx·pdx + pdx² + t²cdy² - 2t·cdy·pdy + pdy² =
     *       = r₁² + 2·r₁·t·dr + t²·dr²
     *
     *     (cdx² + cdy² - dr²)t² - 2(cdx·pdx + cdy·pdy + r₁·dr)t +
     *         (pdx² + pdy² - r₁²) = 0
     *
     *     A = cdx² + cdy² - dr²
     *     B = pdx·cdx + pdy·cdy + r₁·dr
     *     C = pdx² + pdy² - r₁²
     *     At² - 2Bt + C = 0
     *
     * The solutions (unless the equation degenerates because of A = 0) are:
     *
     *     t = (B ± ⎷(B² - A·C)) / A
     *
     * The solution we are going to prefer is the bigger one, unless the
     * radius associated to it is negative (or it falls outside the valid t
     * range).
     *
     * Additional observations (useful for optimizations):
     * A does not depend on p
     *
     * A < 0 <=> one of the two circles completely contains the other one
     *   <=> for every p, the radiuses associated with the two t solutions
     *       have opposite sign
     */
    pixman_image_t *image = iter->image;
    int x = iter->x;
    int y = iter->y;
    int width = iter->width;
    uint32_t *buffer = iter->buffer;

    gradient_t *gradient = (gradient_t *)image;
    radial_gradient_t *radial = (radial_gradient_t *)image;
    uint32_t *end = buffer + width;
    pixman_gradient_walker_t walker;
    pixman_vector_t v, unit;

    /* reference point is the center of the pixel */
    v.vector[0] = pixman_int_to_fixed (x) + pixman_fixed_1 / 2;
    v.vector[1] = pixman_int_to_fixed (y) + pixman_fixed_1 / 2;
    v.vector[2] = pixman_fixed_1;

    _pixman_gradient_walker_init (&walker, gradient, image->common.repeat);

    if (image->common.transform)
    {
	if (!pixman_transform_point_3d (image->common.transform, &v))
	    return iter->buffer;

	unit.vector[0] = image->common.transform->matrix[0][0];
	unit.vector[1] = image->common.transform->matrix[1][0];
	unit.vector[2] = image->common.transform->matrix[2][0];
    }
    else
    {
	unit.vector[0] = pixman_fixed_1;
	unit.vector[1] = 0;
	unit.vector[2] = 0;
    }

    if (unit.vector[2] == 0 && v.vector[2] == pixman_fixed_1)
    {
	/*
	 * Given:
	 *
	 * t = (B ± ⎷(B² - A·C)) / A
	 *
	 * where
	 *
	 * A = cdx² + cdy² - dr²
	 * B = pdx·cdx + pdy·cdy + r₁·dr
	 * C = pdx² + pdy² - r₁²
	 * det = B² - A·C
	 *
	 * Since we have an affine transformation, we know that (pdx, pdy)
	 * increase linearly with each pixel,
	 *
	 * pdx = pdx₀ + n·ux,
	 * pdy = pdy₀ + n·uy,
	 *
	 * we can then express B, C and det through multiple differentiation.
	 */
	pixman_fixed_32_32_t b, db, c, dc, ddc;

	/* warning: this computation may overflow */
	v.vector[0] -= radial->c1.x;
	v.vector[1] -= radial->c1.y;

	/*
	 * B and C are computed and updated exactly.
	 * If fdot was used instead of dot, in the worst case it would
	 * lose 11 bits of precision in each of the multiplication and
	 * summing up would zero out all the bit that were preserved,
	 * thus making the result 0 instead of the correct one.
	 * This would mean a worst case of unbound relative error or
	 * about 2^10 absolute error
	 */
	b = dot (v.vector[0], v.vector[1], radial->c1.radius,
		 radial->delta.x, radial->delta.y, radial->delta.radius);
	db = dot (unit.vector[0], unit.vector[1], 0,
		  radial->delta.x, radial->delta.y, 0);

	c = dot (v.vector[0], v.vector[1],
		 -((pixman_fixed_48_16_t) radial->c1.radius),
		 v.vector[0], v.vector[1], radial->c1.radius);
	dc = dot (2 * (pixman_fixed_48_16_t) v.vector[0] + unit.vector[0],
		  2 * (pixman_fixed_48_16_t) v.vector[1] + unit.vector[1],
		  0,
		  unit.vector[0], unit.vector[1], 0);
	ddc = 2 * dot (unit.vector[0], unit.vector[1], 0,
		       unit.vector[0], unit.vector[1], 0);

	while (buffer < end)
	{
	    if (!mask || *mask++)
	    {
		*buffer = radial_compute_color (radial->a, b, c,
						radial->inva,
						radial->delta.radius,
						radial->mindr,
						&walker,
						image->common.repeat);
	    }

	    b += db;
	    c += dc;
	    dc += ddc;
	    ++buffer;
	}
    }
    else
    {
	/* projective */
	/* Warning:
	 * error propagation guarantees are much looser than in the affine case
	 */
	while (buffer < end)
	{
	    if (!mask || *mask++)
	    {
		if (v.vector[2] != 0)
		{
		    double pdx, pdy, invv2, b, c;

		    invv2 = 1. * pixman_fixed_1 / v.vector[2];

		    pdx = v.vector[0] * invv2 - radial->c1.x;
		    /*    / pixman_fixed_1 */

		    pdy = v.vector[1] * invv2 - radial->c1.y;
		    /*    / pixman_fixed_1 */

		    b = fdot (pdx, pdy, radial->c1.radius,
			      radial->delta.x, radial->delta.y,
			      radial->delta.radius);
		    /*  / pixman_fixed_1 / pixman_fixed_1 */

		    c = fdot (pdx, pdy, -radial->c1.radius,
			      pdx, pdy, radial->c1.radius);
		    /*  / pixman_fixed_1 / pixman_fixed_1 */

		    *buffer = radial_compute_color (radial->a, b, c,
						    radial->inva,
						    radial->delta.radius,
						    radial->mindr,
						    &walker,
						    image->common.repeat);
		}
		else
		{
		    *buffer = 0;
		}
	    }

	    ++buffer;

	    v.vector[0] += unit.vector[0];
	    v.vector[1] += unit.vector[1];
	    v.vector[2] += unit.vector[2];
	}
    }

    iter->y++;
    return iter->buffer;
}
void
_pixman_general_conical_gradient_get_scanline_32 (pixman_image_t *image,
						  int             x,
						  int             y,
						  int             width,
						  uint32_t *      buffer,
						  const uint32_t *mask,
						  uint32_t        mask_bits)
{
    source_image_t *source = (source_image_t *)image;
    gradient_t *gradient = (gradient_t *)source;
    conical_gradient_t *conical = (conical_gradient_t *)image;
    uint32_t       *end = buffer + width;
    pixman_gradient_walker_t walker;
    pixman_bool_t affine = TRUE;
    double cx = 1.;
    double cy = 0.;
    double cz = 0.;
    double rx = x + 0.5;
    double ry = y + 0.5;
    double rz = 1.;
    double a = (conical->angle * M_PI) / (180. * 65536);

    _pixman_gradient_walker_init (&walker, gradient, source->common.repeat);

    if (source->common.transform)
    {
	pixman_vector_t v;

	/* reference point is the center of the pixel */
	v.vector[0] = pixman_int_to_fixed (x) + pixman_fixed_1 / 2;
	v.vector[1] = pixman_int_to_fixed (y) + pixman_fixed_1 / 2;
	v.vector[2] = pixman_fixed_1;

	if (!pixman_transform_point_3d (source->common.transform, &v))
	    return;

	cx = source->common.transform->matrix[0][0] / 65536.;
	cy = source->common.transform->matrix[1][0] / 65536.;
	cz = source->common.transform->matrix[2][0] / 65536.;
	
	rx = v.vector[0] / 65536.;
	ry = v.vector[1] / 65536.;
	rz = v.vector[2] / 65536.;
	
	affine =
	    source->common.transform->matrix[2][0] == 0 &&
	    v.vector[2] == pixman_fixed_1;
    }

    if (affine)
    {
	rx -= conical->center.x / 65536.;
	ry -= conical->center.y / 65536.;

	while (buffer < end)
	{
	    double angle;

	    if (!mask || *mask++ & mask_bits)
	    {
		pixman_fixed_48_16_t t;

		angle = atan2 (ry, rx) + a;
		t     = (pixman_fixed_48_16_t) (angle * (65536. / (2 * M_PI)));

		*buffer = _pixman_gradient_walker_pixel (&walker, t);
	    }

	    ++buffer;
	    
	    rx += cx;
	    ry += cy;
	}
    }
    else
    {
	while (buffer < end)
	{
	    double x, y;
	    double angle;

	    if (!mask || *mask++ & mask_bits)
	    {
		pixman_fixed_48_16_t t;

		if (rz != 0)
		{
		    x = rx / rz;
		    y = ry / rz;
		}
		else
		{
		    x = y = 0.;
		}

		x -= conical->center.x / 65536.;
		y -= conical->center.y / 65536.;
		
		angle = atan2 (y, x) + a;
		t     = (pixman_fixed_48_16_t) (angle * (65536. / (2 * M_PI)));

		*buffer = _pixman_gradient_walker_pixel (&walker, t);
	    }

	    ++buffer;
	    
	    rx += cx;
	    ry += cy;
	    rz += cz;
	}
    }
}
Exemplo n.º 30
0
static uint32_t *
bits_image_fetch_bilinear_no_repeat_8888 (pixman_iter_t *iter,
					  const uint32_t *mask)
{

    pixman_image_t * ima = iter->image;
    int              offset = iter->x;
    int              line = iter->y++;
    int              width = iter->width;
    uint32_t *       buffer = iter->buffer;

    bits_image_t *bits = &ima->bits;
    pixman_fixed_t x_top, x_bottom, x;
    pixman_fixed_t ux_top, ux_bottom, ux;
    pixman_vector_t v;
    uint32_t top_mask, bottom_mask;
    uint32_t *top_row;
    uint32_t *bottom_row;
    uint32_t *end;
    uint32_t zero[2] = { 0, 0 };
    uint32_t one = 1;
    int y, y1, y2;
    int disty;
    int mask_inc;
    int w;

    /* reference point is the center of the pixel */
    v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
    v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
    v.vector[2] = pixman_fixed_1;

    if (!pixman_transform_point_3d (bits->common.transform, &v))
	return iter->buffer;

    ux = ux_top = ux_bottom = bits->common.transform->matrix[0][0];
    x = x_top = x_bottom = v.vector[0] - pixman_fixed_1/2;

    y = v.vector[1] - pixman_fixed_1/2;
    disty = pixman_fixed_to_bilinear_weight (y);

    /* Load the pointers to the first and second lines from the source
     * image that bilinear code must read.
     *
     * The main trick in this code is about the check if any line are
     * outside of the image;
     *
     * When I realize that a line (any one) is outside, I change
     * the pointer to a dummy area with zeros. Once I change this, I
     * must be sure the pointer will not change, so I set the
     * variables to each pointer increments inside the loop.
     */
    y1 = pixman_fixed_to_int (y);
    y2 = y1 + 1;

    if (y1 < 0 || y1 >= bits->height)
    {
	top_row = zero;
	x_top = 0;
	ux_top = 0;
    }
    else
    {
	top_row = bits->bits + y1 * bits->rowstride;
	x_top = x;
	ux_top = ux;
    }

    if (y2 < 0 || y2 >= bits->height)
    {
	bottom_row = zero;
	x_bottom = 0;
	ux_bottom = 0;
    }
    else
    {
	bottom_row = bits->bits + y2 * bits->rowstride;
	x_bottom = x;
	ux_bottom = ux;
    }

    /* Instead of checking whether the operation uses the mast in
     * each loop iteration, verify this only once and prepare the
     * variables to make the code smaller inside the loop.
     */
    if (!mask)
    {
        mask_inc = 0;
        mask = &one;
    }
    else
    {
        /* If have a mask, prepare the variables to check it */
        mask_inc = 1;
    }

    /* If both are zero, then the whole thing is zero */
    if (top_row == zero && bottom_row == zero)
    {
	memset (buffer, 0, width * sizeof (uint32_t));
	return iter->buffer;
    }
    else if (bits->format == PIXMAN_x8r8g8b8)
    {
	if (top_row == zero)
	{
	    top_mask = 0;
	    bottom_mask = 0xff000000;
	}
	else if (bottom_row == zero)
	{
	    top_mask = 0xff000000;
	    bottom_mask = 0;
	}
	else
	{
	    top_mask = 0xff000000;
	    bottom_mask = 0xff000000;
	}
    }
    else
    {
	top_mask = 0;
	bottom_mask = 0;
    }

    end = buffer + width;

    /* Zero fill to the left of the image */
    while (buffer < end && x < pixman_fixed_minus_1)
    {
	*buffer++ = 0;
	x += ux;
	x_top += ux_top;
	x_bottom += ux_bottom;
	mask += mask_inc;
    }

    /* Left edge
     */
    while (buffer < end && x < 0)
    {
	uint32_t tr, br;
	int32_t distx;

	tr = top_row[pixman_fixed_to_int (x_top) + 1] | top_mask;
	br = bottom_row[pixman_fixed_to_int (x_bottom) + 1] | bottom_mask;

	distx = pixman_fixed_to_bilinear_weight (x);

	*buffer++ = bilinear_interpolation (0, tr, 0, br, distx, disty);

	x += ux;
	x_top += ux_top;
	x_bottom += ux_bottom;
	mask += mask_inc;
    }

    /* Main part */
    w = pixman_int_to_fixed (bits->width - 1);

    while (buffer < end  &&  x < w)
    {
	if (*mask)
	{
	    uint32_t tl, tr, bl, br;
	    int32_t distx;

	    tl = top_row [pixman_fixed_to_int (x_top)] | top_mask;
	    tr = top_row [pixman_fixed_to_int (x_top) + 1] | top_mask;
	    bl = bottom_row [pixman_fixed_to_int (x_bottom)] | bottom_mask;
	    br = bottom_row [pixman_fixed_to_int (x_bottom) + 1] | bottom_mask;

	    distx = pixman_fixed_to_bilinear_weight (x);

	    *buffer = bilinear_interpolation (tl, tr, bl, br, distx, disty);
	}

	buffer++;
	x += ux;
	x_top += ux_top;
	x_bottom += ux_bottom;
	mask += mask_inc;
    }

    /* Right Edge */
    w = pixman_int_to_fixed (bits->width);
    while (buffer < end  &&  x < w)
    {
	if (*mask)
	{
	    uint32_t tl, bl;
	    int32_t distx;

	    tl = top_row [pixman_fixed_to_int (x_top)] | top_mask;
	    bl = bottom_row [pixman_fixed_to_int (x_bottom)] | bottom_mask;

	    distx = pixman_fixed_to_bilinear_weight (x);

	    *buffer = bilinear_interpolation (tl, 0, bl, 0, distx, disty);
	}

	buffer++;
	x += ux;
	x_top += ux_top;
	x_bottom += ux_bottom;
	mask += mask_inc;
    }

    /* Zero fill to the left of the image */
    while (buffer < end)
	*buffer++ = 0;

    return iter->buffer;
}