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