static cairo_status_t
_cairo_image_surface_set_matrix (cairo_image_surface_t	*surface,
                                 const cairo_matrix_t	*matrix)
{
    pixman_transform_t pixman_transform;

    //+EAWebKitChange - Added a ref point (width/2, height/2) for shadow box bug fix.
    //6/26/2013
    _cairo_matrix_to_pixman_matrix (matrix, &pixman_transform, surface->width/2., surface->height/2.);
    //-EAWebKitChange

    if (! pixman_image_set_transform (surface->pixman_image, &pixman_transform))
        return _cairo_error (CAIRO_STATUS_NO_MEMORY);

    return CAIRO_STATUS_SUCCESS;
}
Exemple #2
0
/**
 * _cairo_matrix_to_pixman_matrix_offset:
 * @matrix: a matrix
 * @filter: the filter to be used on the pattern transformed by @matrix
 * @xc: the X coordinate of the point to fix in pattern space
 * @yc: the Y coordinate of the point to fix in pattern space
 * @out_transform: the transformation which best approximates @matrix
 * @x_offset: the translation in the X direction
 * @y_offset: the translation in the Y direction
 *
 * This function tries to represent @matrix translated by (x_offset,
 * y_offset) as a %pixman_transform_t and an translation.
 *
 * Passing a non-zero value in x_offset/y_offset has the same effect
 * as applying cairo_matrix_translate(matrix, x_offset, y_offset) and
 * setting x_offset and y_offset to 0.
 *
 * If it is possible to represent the matrix with an identity
 * %pixman_transform_t and a translation within the valid range for
 * pixman, this function will set @out_transform to be the identity,
 * @x_offset and @y_offset to be the translation vector and will
 * return %CAIRO_INT_STATUS_NOTHING_TO_DO. Otherwise it will try to
 * evenly divide the translational component of @matrix between
 * @out_transform and (@x_offset, @y_offset).
 *
 * Upon return x_offset and y_offset contain the translation vector.
 *
 * Return value: %CAIRO_INT_STATUS_NOTHING_TO_DO if the out_transform
 * is the identity, %CAIRO_STATUS_INVALID_MATRIX if it was not
 * possible to represent @matrix as a pixman_transform_t without
 * overflows, %CAIRO_STATUS_SUCCESS otherwise.
 **/
cairo_status_t
_cairo_matrix_to_pixman_matrix_offset (const cairo_matrix_t	*matrix,
				       cairo_filter_t            filter,
				       double                    xc,
				       double                    yc,
				       pixman_transform_t	*out_transform,
				       int                      *x_offset,
				       int                      *y_offset)
{
    cairo_bool_t is_pixman_translation;

    is_pixman_translation = _cairo_matrix_is_pixman_translation (matrix,
								 filter,
								 x_offset,
								 y_offset);

    if (is_pixman_translation) {
	*out_transform = pixman_identity_transform;
	return CAIRO_INT_STATUS_NOTHING_TO_DO;
    } else {
	cairo_matrix_t m;

	m = *matrix;
	cairo_matrix_translate (&m, *x_offset, *y_offset);
	if (m.x0 != 0.0 || m.y0 != 0.0) {
	    double tx, ty, norm;
	    int i, j;

	    /* pixman also limits the [xy]_offset to 16 bits so evenly
	     * spread the bits between the two.
	     *
	     * To do this, find the solutions of:
	     *   |x| = |x*m.xx + y*m.xy + m.x0|
	     *   |y| = |x*m.yx + y*m.yy + m.y0|
	     *
	     * and select the one whose maximum norm is smallest.
	     */
	    tx = m.x0;
	    ty = m.y0;
	    norm = MAX (fabs (tx), fabs (ty));

	    for (i = -1; i < 2; i+=2) {
		for (j = -1; j < 2; j+=2) {
		    double x, y, den, new_norm;

		    den = (m.xx + i) * (m.yy + j) - m.xy * m.yx;
		    if (fabs (den) < DBL_EPSILON)
			continue;

		    x = m.y0 * m.xy - m.x0 * (m.yy + j);
		    y = m.x0 * m.yx - m.y0 * (m.xx + i);

		    den = 1 / den;
		    x *= den;
		    y *= den;

		    new_norm = MAX (fabs (x), fabs (y));
		    if (norm > new_norm) {
			norm = new_norm;
			tx = x;
			ty = y;
		    }
		}
	    }

	    tx = floor (tx);
	    ty = floor (ty);
	    *x_offset = -tx;
	    *y_offset = -ty;
	    cairo_matrix_translate (&m, tx, ty);
	} else {
	    *x_offset = 0;
	    *y_offset = 0;
	}

	return _cairo_matrix_to_pixman_matrix (&m, out_transform, xc, yc);
    }
}