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; }
/** * _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); } }