/* 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;
}
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;
}
static Bool
matrix_from_pict_transform(PictTransform *trans, float *matrix)
{
	if (!trans)
		return FALSE;

	matrix[0] = pixman_fixed_to_double(trans->matrix[0][0]);
	matrix[3] = pixman_fixed_to_double(trans->matrix[0][1]);
	matrix[6] = pixman_fixed_to_double(trans->matrix[0][2]);

	matrix[1] = pixman_fixed_to_double(trans->matrix[1][0]);
	matrix[4] = pixman_fixed_to_double(trans->matrix[1][1]);
	matrix[7] = pixman_fixed_to_double(trans->matrix[1][2]);

	matrix[2] = pixman_fixed_to_double(trans->matrix[2][0]);
	matrix[5] = pixman_fixed_to_double(trans->matrix[2][1]);
	matrix[8] = pixman_fixed_to_double(trans->matrix[2][2]);

	return TRUE;
}
Exemple #4
0
static cairo_status_t
_cairo_matrix_to_pixman_matrix (const cairo_matrix_t	*matrix,
				pixman_transform_t	*pixman_transform,
				double xc,
				double yc)
{
    cairo_matrix_t inv;
    unsigned max_iterations;

    pixman_transform->matrix[0][0] = _cairo_fixed_16_16_from_double (matrix->xx);
    pixman_transform->matrix[0][1] = _cairo_fixed_16_16_from_double (matrix->xy);
    pixman_transform->matrix[0][2] = _cairo_fixed_16_16_from_double (matrix->x0);

    pixman_transform->matrix[1][0] = _cairo_fixed_16_16_from_double (matrix->yx);
    pixman_transform->matrix[1][1] = _cairo_fixed_16_16_from_double (matrix->yy);
    pixman_transform->matrix[1][2] = _cairo_fixed_16_16_from_double (matrix->y0);

    pixman_transform->matrix[2][0] = 0;
    pixman_transform->matrix[2][1] = 0;
    pixman_transform->matrix[2][2] = 1 << 16;

    /* The conversion above breaks cairo's translation invariance:
     * a translation of (a, b) in device space translates to
     * a translation of (xx * a + xy * b, yx * a + yy * b)
     * for cairo, while pixman uses rounded versions of xx ... yy.
     * This error increases as a and b get larger.
     *
     * To compensate for this, we fix the point (xc, yc) in pattern
     * space and adjust pixman's transform to agree with cairo's at
     * that point.
     */

    if (_cairo_matrix_has_unity_scale (matrix))
	return CAIRO_STATUS_SUCCESS;

    if (unlikely (fabs (matrix->xx) > PIXMAN_MAX_INT ||
		  fabs (matrix->xy) > PIXMAN_MAX_INT ||
		  fabs (matrix->x0) > PIXMAN_MAX_INT ||
		  fabs (matrix->yx) > PIXMAN_MAX_INT ||
		  fabs (matrix->yy) > PIXMAN_MAX_INT ||
		  fabs (matrix->y0) > PIXMAN_MAX_INT))
    {
	return _cairo_error (CAIRO_STATUS_INVALID_MATRIX);
    }

    /* Note: If we can't invert the transformation, skip the adjustment. */
    inv = *matrix;
    if (cairo_matrix_invert (&inv) != CAIRO_STATUS_SUCCESS)
	return CAIRO_STATUS_SUCCESS;

    /* find the pattern space coordinate that maps to (xc, yc) */
    max_iterations = 5;
    do {
	double x,y;
	pixman_vector_t vector;
	cairo_fixed_16_16_t dx, dy;

	vector.vector[0] = _cairo_fixed_16_16_from_double (xc);
	vector.vector[1] = _cairo_fixed_16_16_from_double (yc);
	vector.vector[2] = 1 << 16;

	/* If we can't transform the reference point, skip the adjustment. */
	if (! pixman_transform_point_3d (pixman_transform, &vector))
	    return CAIRO_STATUS_SUCCESS;

	x = pixman_fixed_to_double (vector.vector[0]);
	y = pixman_fixed_to_double (vector.vector[1]);
	cairo_matrix_transform_point (&inv, &x, &y);

	/* Ideally, the vector should now be (xc, yc).
	 * We can now compensate for the resulting error.
	 */
	x -= xc;
	y -= yc;
	cairo_matrix_transform_distance (matrix, &x, &y);
	dx = _cairo_fixed_16_16_from_double (x);
	dy = _cairo_fixed_16_16_from_double (y);
	pixman_transform->matrix[0][2] -= dx;
	pixman_transform->matrix[1][2] -= dy;

	if (dx == 0 && dy == 0)
	    return CAIRO_STATUS_SUCCESS;
    } while (--max_iterations);

    /* We didn't find an exact match between cairo and pixman, but
     * the matrix should be mostly correct */
    return CAIRO_STATUS_SUCCESS;
}
Exemple #5
0
void
_cairo_matrix_to_pixman_matrix (const cairo_matrix_t	*matrix,
				pixman_transform_t	*pixman_transform,
				double xc,
				double yc)
{
    static const pixman_transform_t pixman_identity_transform = {{
        {1 << 16,        0,       0},
        {       0, 1 << 16,       0},
        {       0,       0, 1 << 16}
    }};

    if (_cairo_matrix_is_identity (matrix)) {
        *pixman_transform = pixman_identity_transform;
    } else {
        cairo_matrix_t inv;
	unsigned max_iterations;

        pixman_transform->matrix[0][0] = _cairo_fixed_16_16_from_double (matrix->xx);
        pixman_transform->matrix[0][1] = _cairo_fixed_16_16_from_double (matrix->xy);
        pixman_transform->matrix[0][2] = _cairo_fixed_16_16_from_double (matrix->x0);

        pixman_transform->matrix[1][0] = _cairo_fixed_16_16_from_double (matrix->yx);
        pixman_transform->matrix[1][1] = _cairo_fixed_16_16_from_double (matrix->yy);
        pixman_transform->matrix[1][2] = _cairo_fixed_16_16_from_double (matrix->y0);

        pixman_transform->matrix[2][0] = 0;
        pixman_transform->matrix[2][1] = 0;
        pixman_transform->matrix[2][2] = 1 << 16;

        /* The conversion above breaks cairo's translation invariance:
         * a translation of (a, b) in device space translates to
         * a translation of (xx * a + xy * b, yx * a + yy * b)
         * for cairo, while pixman uses rounded versions of xx ... yy.
         * This error increases as a and b get larger.
         *
         * To compensate for this, we fix the point (xc, yc) in pattern
         * space and adjust pixman's transform to agree with cairo's at
         * that point.
	 */

	if (_cairo_matrix_has_unity_scale (matrix))
	    return;

        /* Note: If we can't invert the transformation, skip the adjustment. */
        inv = *matrix;
        if (cairo_matrix_invert (&inv) != CAIRO_STATUS_SUCCESS)
            return;

        /* find the pattern space coordinate that maps to (xc, yc) */
	xc += .5; yc += .5; /* offset for the pixel centre */
	max_iterations = 5;
	do {
	    double x,y;
	    pixman_vector_t vector;
	    cairo_fixed_16_16_t dx, dy;

	    vector.vector[0] = _cairo_fixed_16_16_from_double (xc);
	    vector.vector[1] = _cairo_fixed_16_16_from_double (yc);
	    vector.vector[2] = 1 << 16;

	    if (! pixman_transform_point_3d (pixman_transform, &vector))
		return;

	    x = pixman_fixed_to_double (vector.vector[0]);
	    y = pixman_fixed_to_double (vector.vector[1]);
	    cairo_matrix_transform_point (&inv, &x, &y);

	    /* Ideally, the vector should now be (xc, yc).
	     * We can now compensate for the resulting error.
	     */
	    x -= xc;
	    y -= yc;
	    cairo_matrix_transform_distance (matrix, &x, &y);
	    dx = _cairo_fixed_16_16_from_double (x);
	    dy = _cairo_fixed_16_16_from_double (y);
	    pixman_transform->matrix[0][2] -= dx;
	    pixman_transform->matrix[1][2] -= dy;

	    if (dx == 0 && dy == 0)
		break;
	} while (--max_iterations);
    }
}