⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cairo-matrix.c

📁 按照官方的说法:Cairo is a vector graphics library with cross-device output support. 翻译过来
💻 C
📖 第 1 页 / 共 2 页
字号:
    double dx1, dy1;    double dx2, dy2;    double min_x, max_x;    double min_y, max_y;    quad_x[0] = *x;    quad_y[0] = *y;    cairo_matrix_transform_point (matrix, &quad_x[0], &quad_y[0]);    dx1 = *width;    dy1 = 0;    cairo_matrix_transform_distance (matrix, &dx1, &dy1);    quad_x[1] = quad_x[0] + dx1;    quad_y[1] = quad_y[0] + dy1;    dx2 = 0;    dy2 = *height;    cairo_matrix_transform_distance (matrix, &dx2, &dy2);    quad_x[2] = quad_x[0] + dx2;    quad_y[2] = quad_y[0] + dy2;    quad_x[3] = quad_x[0] + dx1 + dx2;    quad_y[3] = quad_y[0] + dy1 + dy2;    min_x = max_x = quad_x[0];    min_y = max_y = quad_y[0];    for (i=1; i < 4; i++) {	if (quad_x[i] < min_x)	    min_x = quad_x[i];	if (quad_x[i] > max_x)	    max_x = quad_x[i];	if (quad_y[i] < min_y)	    min_y = quad_y[i];	if (quad_y[i] > max_y)	    max_y = quad_y[i];    }    *x = min_x;    *y = min_y;    *width = max_x - min_x;    *height = max_y - min_y;}static void_cairo_matrix_scalar_multiply (cairo_matrix_t *matrix, double scalar){    matrix->xx *= scalar;    matrix->yx *= scalar;    matrix->xy *= scalar;    matrix->yy *= scalar;    matrix->x0 *= scalar;    matrix->y0 *= scalar;}/* This function isn't a correct adjoint in that the implicit 1 in the   homogeneous result should actually be ad-bc instead. But, since this   adjoint is only used in the computation of the inverse, which   divides by det (A)=ad-bc anyway, everything works out in the end. */static void_cairo_matrix_compute_adjoint (cairo_matrix_t *matrix){    /* adj (A) = transpose (C:cofactor (A,i,j)) */    double a, b, c, d, tx, ty;    _cairo_matrix_get_affine (matrix,			      &a,  &b,			      &c,  &d,			      &tx, &ty);    cairo_matrix_init (matrix,		       d, -b,		       -c, a,		       c*ty - d*tx, b*tx - a*ty);}/** * cairo_matrix_invert: * @matrix: a @cairo_matrix_t * * Changes @matrix to be the inverse of it's original value. Not * all transformation matrices have inverses; if the matrix * collapses points together (it is <firstterm>degenerate</firstterm>), * then it has no inverse and this function will fail. * * Returns: If @matrix has an inverse, modifies @matrix to *  be the inverse matrix and returns %CAIRO_STATUS_SUCCESS. Otherwise, *  returns %CAIRO_STATUS_INVALID_MATRIX. **/cairo_status_tcairo_matrix_invert (cairo_matrix_t *matrix){    /* inv (A) = 1/det (A) * adj (A) */    double det;    _cairo_matrix_compute_determinant (matrix, &det);    if (det == 0)	return CAIRO_STATUS_INVALID_MATRIX;    _cairo_matrix_compute_adjoint (matrix);    _cairo_matrix_scalar_multiply (matrix, 1 / det);    return CAIRO_STATUS_SUCCESS;}slim_hidden_def(cairo_matrix_invert);void_cairo_matrix_compute_determinant (const cairo_matrix_t *matrix,				   double		*det){    double a, b, c, d;    a = matrix->xx; b = matrix->yx;    c = matrix->xy; d = matrix->yy;    *det = a*d - b*c;}/* Compute the amount that each basis vector is scaled by. */cairo_status_t_cairo_matrix_compute_scale_factors (const cairo_matrix_t *matrix,				     double *sx, double *sy, int x_major){    double det;    _cairo_matrix_compute_determinant (matrix, &det);    if (det == 0)    {	*sx = *sy = 0;    }    else    {	double x = x_major != 0;	double y = x == 0;	double major, minor;	cairo_matrix_transform_distance (matrix, &x, &y);	major = sqrt(x*x + y*y);	/*	 * ignore mirroring	 */	if (det < 0)	    det = -det;	if (major)	    minor = det / major;	else	    minor = 0.0;	if (x_major)	{	    *sx = major;	    *sy = minor;	}	else	{	    *sx = minor;	    *sy = major;	}    }    return CAIRO_STATUS_SUCCESS;}cairo_bool_t_cairo_matrix_is_identity (const cairo_matrix_t *matrix){    return (matrix->xx == 1.0 && matrix->yx == 0.0 &&	    matrix->xy == 0.0 && matrix->yy == 1.0 &&	    matrix->x0 == 0.0 && matrix->y0 == 0.0);}cairo_bool_t_cairo_matrix_is_integer_translation(const cairo_matrix_t *m,				     int *itx, int *ity){    cairo_bool_t is_integer_translation;    cairo_fixed_t x0_fixed, y0_fixed;    x0_fixed = _cairo_fixed_from_double (m->x0);    y0_fixed = _cairo_fixed_from_double (m->y0);    is_integer_translation = ((m->xx == 1.0) &&			      (m->yx == 0.0) &&			      (m->xy == 0.0) &&			      (m->yy == 1.0) &&			      (_cairo_fixed_is_integer(x0_fixed)) &&			      (_cairo_fixed_is_integer(y0_fixed)));    if (! is_integer_translation)	return FALSE;    if (itx)	*itx = _cairo_fixed_integer_part(x0_fixed);    if (ity)	*ity = _cairo_fixed_integer_part(y0_fixed);    return TRUE;}/*  A circle in user space is transformed into an ellipse in device space.  The following is a derivation of a formula to calculate the length of the  major axis for this ellipse; this is useful for error bounds calculations.  Thanks to Walter Brisken <wbrisken@aoc.nrao.edu> for this derivation:  1.  First some notation:  All capital letters represent vectors in two dimensions.  A prime '  represents a transformed coordinate.  Matrices are written in underlined  form, ie _R_.  Lowercase letters represent scalar real values.  2.  The question has been posed:  What is the maximum expansion factor  achieved by the linear transformation  X' = X _R_  where _R_ is a real-valued 2x2 matrix with entries:  _R_ = [a b]        [c d]  .  In other words, what is the maximum radius, MAX[ |X'| ], reached for any  X on the unit circle ( |X| = 1 ) ?  3.  Some useful formulae  (A) through (C) below are standard double-angle formulae.  (D) is a lesser  known result and is derived below:  (A)  sin²(θ) = (1 - cos(2*θ))/2  (B)  cos²(θ) = (1 + cos(2*θ))/2  (C)  sin(θ)*cos(θ) = sin(2*θ)/2  (D)  MAX[a*cos(θ) + b*sin(θ)] = sqrt(a² + b²)  Proof of (D):  find the maximum of the function by setting the derivative to zero:       -a*sin(θ)+b*cos(θ) = 0  From this it follows that       tan(θ) = b/a  and hence       sin(θ) = b/sqrt(a² + b²)  and       cos(θ) = a/sqrt(a² + b²)  Thus the maximum value is       MAX[a*cos(θ) + b*sin(θ)] = (a² + b²)/sqrt(a² + b²)                                   = sqrt(a² + b²)  4.  Derivation of maximum expansion  To find MAX[ |X'| ] we search brute force method using calculus.  The unit  circle on which X is constrained is to be parameterized by t:       X(θ) = (cos(θ), sin(θ))  Thus       X'(θ) = X(θ) * _R_ = (cos(θ), sin(θ)) * [a b]                                               [c d]             = (a*cos(θ) + c*sin(θ), b*cos(θ) + d*sin(θ)).  Define       r(θ) = |X'(θ)|  Thus       r²(θ) = (a*cos(θ) + c*sin(θ))² + (b*cos(θ) + d*sin(θ))²             = (a² + b²)*cos²(θ) + (c² + d²)*sin²(θ)                 + 2*(a*c + b*d)*cos(θ)*sin(θ)  Now apply the double angle formulae (A) to (C) from above:       r²(θ) = (a² + b² + c² + d²)/2	     + (a² + b² - c² - d²)*cos(2*θ)/2  	     + (a*c + b*d)*sin(2*θ)             = f + g*cos(φ) + h*sin(φ)  Where       f = (a² + b² + c² + d²)/2       g = (a² + b² - c² - d²)/2       h = (a*c + d*d)       φ = 2*θ  It is clear that MAX[ |X'| ] = sqrt(MAX[ r² ]).  Here we determine MAX[ r² ]  using (D) from above:       MAX[ r² ] = f + sqrt(g² + h²)  And finally       MAX[ |X'| ] = sqrt( f + sqrt(g² + h²) )  Which is the solution to this problem.  Walter Brisken  2004/10/08  (Note that the minor axis length is at the minimum of the above solution,  which is just sqrt ( f - sqrt(g² + h²) ) given the symmetry of (D)).*//* determine the length of the major axis of a circle of the given radius   after applying the transformation matrix. */double_cairo_matrix_transformed_circle_major_axis (cairo_matrix_t *matrix, double radius){    double  a, b, c, d, f, g, h, i, j;    _cairo_matrix_get_affine (matrix,                              &a, &b,                              &c, &d,                              NULL, NULL);    i = a*a + b*b;    j = c*c + d*d;    f = 0.5 * (i + j);    g = 0.5 * (i - j);    h = a*c + b*d;    return radius * sqrt (f + sqrt (g*g+h*h));    /*     * we don't need the minor axis length, which is     * double min = radius * sqrt (f - sqrt (g*g+h*h));     */}void_cairo_matrix_to_pixman_matrix (const cairo_matrix_t	*matrix,				pixman_transform_t	*pixman_transform){    pixman_transform->matrix[0][0] = _cairo_fixed_from_double (matrix->xx);    pixman_transform->matrix[0][1] = _cairo_fixed_from_double (matrix->xy);    pixman_transform->matrix[0][2] = _cairo_fixed_from_double (matrix->x0);    pixman_transform->matrix[1][0] = _cairo_fixed_from_double (matrix->yx);    pixman_transform->matrix[1][1] = _cairo_fixed_from_double (matrix->yy);    pixman_transform->matrix[1][2] = _cairo_fixed_from_double (matrix->y0);    pixman_transform->matrix[2][0] = 0;    pixman_transform->matrix[2][1] = 0;    pixman_transform->matrix[2][2] = _cairo_fixed_from_double (1);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -