Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /* cairo - a vector graphics library with display and print output
  2.  *
  3.  * Copyright © 2002 University of Southern California
  4.  *
  5.  * This library is free software; you can redistribute it and/or
  6.  * modify it either under the terms of the GNU Lesser General Public
  7.  * License version 2.1 as published by the Free Software Foundation
  8.  * (the "LGPL") or, at your option, under the terms of the Mozilla
  9.  * Public License Version 1.1 (the "MPL"). If you do not alter this
  10.  * notice, a recipient may use your version of this file under either
  11.  * the MPL or the LGPL.
  12.  *
  13.  * You should have received a copy of the LGPL along with this library
  14.  * in the file COPYING-LGPL-2.1; if not, write to the Free Software
  15.  * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
  16.  * You should have received a copy of the MPL along with this library
  17.  * in the file COPYING-MPL-1.1
  18.  *
  19.  * The contents of this file are subject to the Mozilla Public License
  20.  * Version 1.1 (the "License"); you may not use this file except in
  21.  * compliance with the License. You may obtain a copy of the License at
  22.  * http://www.mozilla.org/MPL/
  23.  *
  24.  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
  25.  * OF ANY KIND, either express or implied. See the LGPL or the MPL for
  26.  * the specific language governing rights and limitations.
  27.  *
  28.  * The Original Code is the cairo graphics library.
  29.  *
  30.  * The Initial Developer of the Original Code is University of Southern
  31.  * California.
  32.  *
  33.  * Contributor(s):
  34.  *      Carl D. Worth <cworth@cworth.org>
  35.  */
  36.  
  37. #include "cairoint.h"
  38. #include "cairo-error-private.h"
  39.  
  40. #if _XOPEN_SOURCE >= 600 || defined (_ISOC99_SOURCE)
  41. #define ISFINITE(x) isfinite (x)
  42. #else
  43. #define ISFINITE(x) ((x) * (x) >= 0.) /* check for NaNs */
  44. #endif
  45.  
  46. /**
  47.  * SECTION:cairo-matrix
  48.  * @Title: cairo_matrix_t
  49.  * @Short_Description: Generic matrix operations
  50.  * @See_Also: #cairo_t
  51.  *
  52.  * #cairo_matrix_t is used throughout cairo to convert between different
  53.  * coordinate spaces.  A #cairo_matrix_t holds an affine transformation,
  54.  * such as a scale, rotation, shear, or a combination of these.
  55.  * The transformation of a point (<literal>x</literal>,<literal>y</literal>)
  56.  * is given by:
  57.  *
  58.  * <programlisting>
  59.  * x_new = xx * x + xy * y + x0;
  60.  * y_new = yx * x + yy * y + y0;
  61.  * </programlisting>
  62.  *
  63.  * The current transformation matrix of a #cairo_t, represented as a
  64.  * #cairo_matrix_t, defines the transformation from user-space
  65.  * coordinates to device-space coordinates. See cairo_get_matrix() and
  66.  * cairo_set_matrix().
  67.  */
  68.  
  69. static void
  70. _cairo_matrix_scalar_multiply (cairo_matrix_t *matrix, double scalar);
  71.  
  72. static void
  73. _cairo_matrix_compute_adjoint (cairo_matrix_t *matrix);
  74.  
  75. /**
  76.  * cairo_matrix_init_identity:
  77.  * @matrix: a #cairo_matrix_t
  78.  *
  79.  * Modifies @matrix to be an identity transformation.
  80.  **/
  81. void
  82. cairo_matrix_init_identity (cairo_matrix_t *matrix)
  83. {
  84.     cairo_matrix_init (matrix,
  85.                        1, 0,
  86.                        0, 1,
  87.                        0, 0);
  88. }
  89. slim_hidden_def(cairo_matrix_init_identity);
  90.  
  91. /**
  92.  * cairo_matrix_init:
  93.  * @matrix: a #cairo_matrix_t
  94.  * @xx: xx component of the affine transformation
  95.  * @yx: yx component of the affine transformation
  96.  * @xy: xy component of the affine transformation
  97.  * @yy: yy component of the affine transformation
  98.  * @x0: X translation component of the affine transformation
  99.  * @y0: Y translation component of the affine transformation
  100.  *
  101.  * Sets @matrix to be the affine transformation given by
  102.  * @xx, @yx, @xy, @yy, @x0, @y0. The transformation is given
  103.  * by:
  104.  * <programlisting>
  105.  *  x_new = xx * x + xy * y + x0;
  106.  *  y_new = yx * x + yy * y + y0;
  107.  * </programlisting>
  108.  **/
  109. void
  110. cairo_matrix_init (cairo_matrix_t *matrix,
  111.                    double xx, double yx,
  112.  
  113.                    double xy, double yy,
  114.                    double x0, double y0)
  115. {
  116.     matrix->xx = xx; matrix->yx = yx;
  117.     matrix->xy = xy; matrix->yy = yy;
  118.     matrix->x0 = x0; matrix->y0 = y0;
  119. }
  120. slim_hidden_def(cairo_matrix_init);
  121.  
  122. /**
  123.  * _cairo_matrix_get_affine:
  124.  * @matrix: a #cairo_matrix_t
  125.  * @xx: location to store xx component of matrix
  126.  * @yx: location to store yx component of matrix
  127.  * @xy: location to store xy component of matrix
  128.  * @yy: location to store yy component of matrix
  129.  * @x0: location to store x0 (X-translation component) of matrix, or %NULL
  130.  * @y0: location to store y0 (Y-translation component) of matrix, or %NULL
  131.  *
  132.  * Gets the matrix values for the affine transformation that @matrix represents.
  133.  * See cairo_matrix_init().
  134.  *
  135.  *
  136.  * This function is a leftover from the old public API, but is still
  137.  * mildly useful as an internal means for getting at the matrix
  138.  * members in a positional way. For example, when reassigning to some
  139.  * external matrix type, or when renaming members to more meaningful
  140.  * names (such as a,b,c,d,e,f) for particular manipulations.
  141.  **/
  142. void
  143. _cairo_matrix_get_affine (const cairo_matrix_t *matrix,
  144.                           double *xx, double *yx,
  145.                           double *xy, double *yy,
  146.                           double *x0, double *y0)
  147. {
  148.     *xx  = matrix->xx;
  149.     *yx  = matrix->yx;
  150.  
  151.     *xy  = matrix->xy;
  152.     *yy  = matrix->yy;
  153.  
  154.     if (x0)
  155.         *x0 = matrix->x0;
  156.     if (y0)
  157.         *y0 = matrix->y0;
  158. }
  159.  
  160. /**
  161.  * cairo_matrix_init_translate:
  162.  * @matrix: a #cairo_matrix_t
  163.  * @tx: amount to translate in the X direction
  164.  * @ty: amount to translate in the Y direction
  165.  *
  166.  * Initializes @matrix to a transformation that translates by @tx and
  167.  * @ty in the X and Y dimensions, respectively.
  168.  **/
  169. void
  170. cairo_matrix_init_translate (cairo_matrix_t *matrix,
  171.                              double tx, double ty)
  172. {
  173.     cairo_matrix_init (matrix,
  174.                        1, 0,
  175.                        0, 1,
  176.                        tx, ty);
  177. }
  178. slim_hidden_def(cairo_matrix_init_translate);
  179.  
  180. /**
  181.  * cairo_matrix_translate:
  182.  * @matrix: a #cairo_matrix_t
  183.  * @tx: amount to translate in the X direction
  184.  * @ty: amount to translate in the Y direction
  185.  *
  186.  * Applies a translation by @tx, @ty to the transformation in
  187.  * @matrix. The effect of the new transformation is to first translate
  188.  * the coordinates by @tx and @ty, then apply the original transformation
  189.  * to the coordinates.
  190.  **/
  191. void
  192. cairo_matrix_translate (cairo_matrix_t *matrix, double tx, double ty)
  193. {
  194.     cairo_matrix_t tmp;
  195.  
  196.     cairo_matrix_init_translate (&tmp, tx, ty);
  197.  
  198.     cairo_matrix_multiply (matrix, &tmp, matrix);
  199. }
  200. slim_hidden_def (cairo_matrix_translate);
  201.  
  202. /**
  203.  * cairo_matrix_init_scale:
  204.  * @matrix: a #cairo_matrix_t
  205.  * @sx: scale factor in the X direction
  206.  * @sy: scale factor in the Y direction
  207.  *
  208.  * Initializes @matrix to a transformation that scales by @sx and @sy
  209.  * in the X and Y dimensions, respectively.
  210.  **/
  211. void
  212. cairo_matrix_init_scale (cairo_matrix_t *matrix,
  213.                          double sx, double sy)
  214. {
  215.     cairo_matrix_init (matrix,
  216.                        sx,  0,
  217.                        0, sy,
  218.                        0, 0);
  219. }
  220. slim_hidden_def(cairo_matrix_init_scale);
  221.  
  222. /**
  223.  * cairo_matrix_scale:
  224.  * @matrix: a #cairo_matrix_t
  225.  * @sx: scale factor in the X direction
  226.  * @sy: scale factor in the Y direction
  227.  *
  228.  * Applies scaling by @sx, @sy to the transformation in @matrix. The
  229.  * effect of the new transformation is to first scale the coordinates
  230.  * by @sx and @sy, then apply the original transformation to the coordinates.
  231.  **/
  232. void
  233. cairo_matrix_scale (cairo_matrix_t *matrix, double sx, double sy)
  234. {
  235.     cairo_matrix_t tmp;
  236.  
  237.     cairo_matrix_init_scale (&tmp, sx, sy);
  238.  
  239.     cairo_matrix_multiply (matrix, &tmp, matrix);
  240. }
  241. slim_hidden_def(cairo_matrix_scale);
  242.  
  243. /**
  244.  * cairo_matrix_init_rotate:
  245.  * @matrix: a #cairo_matrix_t
  246.  * @radians: angle of rotation, in radians. The direction of rotation
  247.  * is defined such that positive angles rotate in the direction from
  248.  * the positive X axis toward the positive Y axis. With the default
  249.  * axis orientation of cairo, positive angles rotate in a clockwise
  250.  * direction.
  251.  *
  252.  * Initialized @matrix to a transformation that rotates by @radians.
  253.  **/
  254. void
  255. cairo_matrix_init_rotate (cairo_matrix_t *matrix,
  256.                           double radians)
  257. {
  258.     double  s;
  259.     double  c;
  260.  
  261.     s = sin (radians);
  262.     c = cos (radians);
  263.  
  264.     cairo_matrix_init (matrix,
  265.                        c, s,
  266.                        -s, c,
  267.                        0, 0);
  268. }
  269. slim_hidden_def(cairo_matrix_init_rotate);
  270.  
  271. /**
  272.  * cairo_matrix_rotate:
  273.  * @matrix: a #cairo_matrix_t
  274.  * @radians: angle of rotation, in radians. The direction of rotation
  275.  * is defined such that positive angles rotate in the direction from
  276.  * the positive X axis toward the positive Y axis. With the default
  277.  * axis orientation of cairo, positive angles rotate in a clockwise
  278.  * direction.
  279.  *
  280.  * Applies rotation by @radians to the transformation in
  281.  * @matrix. The effect of the new transformation is to first rotate the
  282.  * coordinates by @radians, then apply the original transformation
  283.  * to the coordinates.
  284.  **/
  285. void
  286. cairo_matrix_rotate (cairo_matrix_t *matrix, double radians)
  287. {
  288.     cairo_matrix_t tmp;
  289.  
  290.     cairo_matrix_init_rotate (&tmp, radians);
  291.  
  292.     cairo_matrix_multiply (matrix, &tmp, matrix);
  293. }
  294.  
  295. /**
  296.  * cairo_matrix_multiply:
  297.  * @result: a #cairo_matrix_t in which to store the result
  298.  * @a: a #cairo_matrix_t
  299.  * @b: a #cairo_matrix_t
  300.  *
  301.  * Multiplies the affine transformations in @a and @b together
  302.  * and stores the result in @result. The effect of the resulting
  303.  * transformation is to first apply the transformation in @a to the
  304.  * coordinates and then apply the transformation in @b to the
  305.  * coordinates.
  306.  *
  307.  * It is allowable for @result to be identical to either @a or @b.
  308.  **/
  309. /*
  310.  * XXX: The ordering of the arguments to this function corresponds
  311.  *      to [row_vector]*A*B. If we want to use column vectors instead,
  312.  *      then we need to switch the two arguments and fix up all
  313.  *      uses.
  314.  */
  315. void
  316. cairo_matrix_multiply (cairo_matrix_t *result, const cairo_matrix_t *a, const cairo_matrix_t *b)
  317. {
  318.     cairo_matrix_t r;
  319.  
  320.     r.xx = a->xx * b->xx + a->yx * b->xy;
  321.     r.yx = a->xx * b->yx + a->yx * b->yy;
  322.  
  323.     r.xy = a->xy * b->xx + a->yy * b->xy;
  324.     r.yy = a->xy * b->yx + a->yy * b->yy;
  325.  
  326.     r.x0 = a->x0 * b->xx + a->y0 * b->xy + b->x0;
  327.     r.y0 = a->x0 * b->yx + a->y0 * b->yy + b->y0;
  328.  
  329.     *result = r;
  330. }
  331. slim_hidden_def(cairo_matrix_multiply);
  332.  
  333. /**
  334.  * cairo_matrix_transform_distance:
  335.  * @matrix: a #cairo_matrix_t
  336.  * @dx: X component of a distance vector. An in/out parameter
  337.  * @dy: Y component of a distance vector. An in/out parameter
  338.  *
  339.  * Transforms the distance vector (@dx,@dy) by @matrix. This is
  340.  * similar to cairo_matrix_transform_point() except that the translation
  341.  * components of the transformation are ignored. The calculation of
  342.  * the returned vector is as follows:
  343.  *
  344.  * <programlisting>
  345.  * dx2 = dx1 * a + dy1 * c;
  346.  * dy2 = dx1 * b + dy1 * d;
  347.  * </programlisting>
  348.  *
  349.  * Affine transformations are position invariant, so the same vector
  350.  * always transforms to the same vector. If (@x1,@y1) transforms
  351.  * to (@x2,@y2) then (@x1+@dx1,@y1+@dy1) will transform to
  352.  * (@x1+@dx2,@y1+@dy2) for all values of @x1 and @x2.
  353.  **/
  354. void
  355. cairo_matrix_transform_distance (const cairo_matrix_t *matrix, double *dx, double *dy)
  356. {
  357.     double new_x, new_y;
  358.  
  359.     new_x = (matrix->xx * *dx + matrix->xy * *dy);
  360.     new_y = (matrix->yx * *dx + matrix->yy * *dy);
  361.  
  362.     *dx = new_x;
  363.     *dy = new_y;
  364. }
  365. slim_hidden_def(cairo_matrix_transform_distance);
  366.  
  367. /**
  368.  * cairo_matrix_transform_point:
  369.  * @matrix: a #cairo_matrix_t
  370.  * @x: X position. An in/out parameter
  371.  * @y: Y position. An in/out parameter
  372.  *
  373.  * Transforms the point (@x, @y) by @matrix.
  374.  **/
  375. void
  376. cairo_matrix_transform_point (const cairo_matrix_t *matrix, double *x, double *y)
  377. {
  378.     cairo_matrix_transform_distance (matrix, x, y);
  379.  
  380.     *x += matrix->x0;
  381.     *y += matrix->y0;
  382. }
  383. slim_hidden_def(cairo_matrix_transform_point);
  384.  
  385. void
  386. _cairo_matrix_transform_bounding_box (const cairo_matrix_t *matrix,
  387.                                       double *x1, double *y1,
  388.                                       double *x2, double *y2,
  389.                                       cairo_bool_t *is_tight)
  390. {
  391.     int i;
  392.     double quad_x[4], quad_y[4];
  393.     double min_x, max_x;
  394.     double min_y, max_y;
  395.  
  396.     if (matrix->xy == 0. && matrix->yx == 0.) {
  397.         /* non-rotation/skew matrix, just map the two extreme points */
  398.  
  399.         if (matrix->xx != 1.) {
  400.             quad_x[0] = *x1 * matrix->xx;
  401.             quad_x[1] = *x2 * matrix->xx;
  402.             if (quad_x[0] < quad_x[1]) {
  403.                 *x1 = quad_x[0];
  404.                 *x2 = quad_x[1];
  405.             } else {
  406.                 *x1 = quad_x[1];
  407.                 *x2 = quad_x[0];
  408.             }
  409.         }
  410.         if (matrix->x0 != 0.) {
  411.             *x1 += matrix->x0;
  412.             *x2 += matrix->x0;
  413.         }
  414.  
  415.         if (matrix->yy != 1.) {
  416.             quad_y[0] = *y1 * matrix->yy;
  417.             quad_y[1] = *y2 * matrix->yy;
  418.             if (quad_y[0] < quad_y[1]) {
  419.                 *y1 = quad_y[0];
  420.                 *y2 = quad_y[1];
  421.             } else {
  422.                 *y1 = quad_y[1];
  423.                 *y2 = quad_y[0];
  424.             }
  425.         }
  426.         if (matrix->y0 != 0.) {
  427.             *y1 += matrix->y0;
  428.             *y2 += matrix->y0;
  429.         }
  430.  
  431.         if (is_tight)
  432.             *is_tight = TRUE;
  433.  
  434.         return;
  435.     }
  436.  
  437.     /* general matrix */
  438.     quad_x[0] = *x1;
  439.     quad_y[0] = *y1;
  440.     cairo_matrix_transform_point (matrix, &quad_x[0], &quad_y[0]);
  441.  
  442.     quad_x[1] = *x2;
  443.     quad_y[1] = *y1;
  444.     cairo_matrix_transform_point (matrix, &quad_x[1], &quad_y[1]);
  445.  
  446.     quad_x[2] = *x1;
  447.     quad_y[2] = *y2;
  448.     cairo_matrix_transform_point (matrix, &quad_x[2], &quad_y[2]);
  449.  
  450.     quad_x[3] = *x2;
  451.     quad_y[3] = *y2;
  452.     cairo_matrix_transform_point (matrix, &quad_x[3], &quad_y[3]);
  453.  
  454.     min_x = max_x = quad_x[0];
  455.     min_y = max_y = quad_y[0];
  456.  
  457.     for (i=1; i < 4; i++) {
  458.         if (quad_x[i] < min_x)
  459.             min_x = quad_x[i];
  460.         if (quad_x[i] > max_x)
  461.             max_x = quad_x[i];
  462.  
  463.         if (quad_y[i] < min_y)
  464.             min_y = quad_y[i];
  465.         if (quad_y[i] > max_y)
  466.             max_y = quad_y[i];
  467.     }
  468.  
  469.     *x1 = min_x;
  470.     *y1 = min_y;
  471.     *x2 = max_x;
  472.     *y2 = max_y;
  473.  
  474.     if (is_tight) {
  475.         /* it's tight if and only if the four corner points form an axis-aligned
  476.            rectangle.
  477.            And that's true if and only if we can derive corners 0 and 3 from
  478.            corners 1 and 2 in one of two straightforward ways...
  479.            We could use a tolerance here but for now we'll fall back to FALSE in the case
  480.            of floating point error.
  481.         */
  482.         *is_tight =
  483.             (quad_x[1] == quad_x[0] && quad_y[1] == quad_y[3] &&
  484.              quad_x[2] == quad_x[3] && quad_y[2] == quad_y[0]) ||
  485.             (quad_x[1] == quad_x[3] && quad_y[1] == quad_y[0] &&
  486.              quad_x[2] == quad_x[0] && quad_y[2] == quad_y[3]);
  487.     }
  488. }
  489.  
  490. cairo_private void
  491. _cairo_matrix_transform_bounding_box_fixed (const cairo_matrix_t *matrix,
  492.                                             cairo_box_t          *bbox,
  493.                                             cairo_bool_t *is_tight)
  494. {
  495.     double x1, y1, x2, y2;
  496.  
  497.     _cairo_box_to_doubles (bbox, &x1, &y1, &x2, &y2);
  498.     _cairo_matrix_transform_bounding_box (matrix, &x1, &y1, &x2, &y2, is_tight);
  499.     _cairo_box_from_doubles (bbox, &x1, &y1, &x2, &y2);
  500. }
  501.  
  502. static void
  503. _cairo_matrix_scalar_multiply (cairo_matrix_t *matrix, double scalar)
  504. {
  505.     matrix->xx *= scalar;
  506.     matrix->yx *= scalar;
  507.  
  508.     matrix->xy *= scalar;
  509.     matrix->yy *= scalar;
  510.  
  511.     matrix->x0 *= scalar;
  512.     matrix->y0 *= scalar;
  513. }
  514.  
  515. /* This function isn't a correct adjoint in that the implicit 1 in the
  516.    homogeneous result should actually be ad-bc instead. But, since this
  517.    adjoint is only used in the computation of the inverse, which
  518.    divides by det (A)=ad-bc anyway, everything works out in the end. */
  519. static void
  520. _cairo_matrix_compute_adjoint (cairo_matrix_t *matrix)
  521. {
  522.     /* adj (A) = transpose (C:cofactor (A,i,j)) */
  523.     double a, b, c, d, tx, ty;
  524.  
  525.     _cairo_matrix_get_affine (matrix,
  526.                               &a,  &b,
  527.                               &c,  &d,
  528.                               &tx, &ty);
  529.  
  530.     cairo_matrix_init (matrix,
  531.                        d, -b,
  532.                        -c, a,
  533.                        c*ty - d*tx, b*tx - a*ty);
  534. }
  535.  
  536. /**
  537.  * cairo_matrix_invert:
  538.  * @matrix: a #cairo_matrix_t
  539.  *
  540.  * Changes @matrix to be the inverse of its original value. Not
  541.  * all transformation matrices have inverses; if the matrix
  542.  * collapses points together (it is <firstterm>degenerate</firstterm>),
  543.  * then it has no inverse and this function will fail.
  544.  *
  545.  * Returns: If @matrix has an inverse, modifies @matrix to
  546.  *  be the inverse matrix and returns %CAIRO_STATUS_SUCCESS. Otherwise,
  547.  *  returns %CAIRO_STATUS_INVALID_MATRIX.
  548.  **/
  549. cairo_status_t
  550. cairo_matrix_invert (cairo_matrix_t *matrix)
  551. {
  552.     double det;
  553.  
  554.     /* Simple scaling|translation matrices are quite common... */
  555.     if (matrix->xy == 0. && matrix->yx == 0.) {
  556.         matrix->x0 = -matrix->x0;
  557.         matrix->y0 = -matrix->y0;
  558.  
  559.         if (matrix->xx != 1.) {
  560.             if (matrix->xx == 0.)
  561.                 return _cairo_error (CAIRO_STATUS_INVALID_MATRIX);
  562.  
  563.             matrix->xx = 1. / matrix->xx;
  564.             matrix->x0 *= matrix->xx;
  565.         }
  566.  
  567.         if (matrix->yy != 1.) {
  568.             if (matrix->yy == 0.)
  569.                 return _cairo_error (CAIRO_STATUS_INVALID_MATRIX);
  570.  
  571.             matrix->yy = 1. / matrix->yy;
  572.             matrix->y0 *= matrix->yy;
  573.         }
  574.  
  575.         return CAIRO_STATUS_SUCCESS;
  576.     }
  577.  
  578.     /* inv (A) = 1/det (A) * adj (A) */
  579.     det = _cairo_matrix_compute_determinant (matrix);
  580.  
  581.     if (! ISFINITE (det))
  582.         return _cairo_error (CAIRO_STATUS_INVALID_MATRIX);
  583.  
  584.     if (det == 0)
  585.         return _cairo_error (CAIRO_STATUS_INVALID_MATRIX);
  586.  
  587.     _cairo_matrix_compute_adjoint (matrix);
  588.     _cairo_matrix_scalar_multiply (matrix, 1 / det);
  589.  
  590.     return CAIRO_STATUS_SUCCESS;
  591. }
  592. slim_hidden_def(cairo_matrix_invert);
  593.  
  594. cairo_bool_t
  595. _cairo_matrix_is_invertible (const cairo_matrix_t *matrix)
  596. {
  597.     double det;
  598.  
  599.     det = _cairo_matrix_compute_determinant (matrix);
  600.  
  601.     return ISFINITE (det) && det != 0.;
  602. }
  603.  
  604. cairo_bool_t
  605. _cairo_matrix_is_scale_0 (const cairo_matrix_t *matrix)
  606. {
  607.     return matrix->xx == 0. &&
  608.            matrix->xy == 0. &&
  609.            matrix->yx == 0. &&
  610.            matrix->yy == 0.;
  611. }
  612.  
  613. double
  614. _cairo_matrix_compute_determinant (const cairo_matrix_t *matrix)
  615. {
  616.     double a, b, c, d;
  617.  
  618.     a = matrix->xx; b = matrix->yx;
  619.     c = matrix->xy; d = matrix->yy;
  620.  
  621.     return a*d - b*c;
  622. }
  623.  
  624. /**
  625.  * _cairo_matrix_compute_basis_scale_factors:
  626.  * @matrix: a matrix
  627.  * @basis_scale: the scale factor in the direction of basis
  628.  * @normal_scale: the scale factor in the direction normal to the basis
  629.  * @x_basis: basis to use.  X basis if true, Y basis otherwise.
  630.  *
  631.  * Computes |Mv| and det(M)/|Mv| for v=[1,0] if x_basis is true, and v=[0,1]
  632.  * otherwise, and M is @matrix.
  633.  *
  634.  * Return value: the scale factor of @matrix on the height of the font,
  635.  * or 1.0 if @matrix is %NULL.
  636.  **/
  637. cairo_status_t
  638. _cairo_matrix_compute_basis_scale_factors (const cairo_matrix_t *matrix,
  639.                                            double *basis_scale, double *normal_scale,
  640.                                            cairo_bool_t x_basis)
  641. {
  642.     double det;
  643.  
  644.     det = _cairo_matrix_compute_determinant (matrix);
  645.  
  646.     if (! ISFINITE (det))
  647.         return _cairo_error (CAIRO_STATUS_INVALID_MATRIX);
  648.  
  649.     if (det == 0)
  650.     {
  651.         *basis_scale = *normal_scale = 0;
  652.     }
  653.     else
  654.     {
  655.         double x = x_basis != 0;
  656.         double y = x == 0;
  657.         double major, minor;
  658.  
  659.         cairo_matrix_transform_distance (matrix, &x, &y);
  660.         major = hypot (x, y);
  661.         /*
  662.          * ignore mirroring
  663.          */
  664.         if (det < 0)
  665.             det = -det;
  666.         if (major)
  667.             minor = det / major;
  668.         else
  669.             minor = 0.0;
  670.         if (x_basis)
  671.         {
  672.             *basis_scale = major;
  673.             *normal_scale = minor;
  674.         }
  675.         else
  676.         {
  677.             *basis_scale = minor;
  678.             *normal_scale = major;
  679.         }
  680.     }
  681.  
  682.     return CAIRO_STATUS_SUCCESS;
  683. }
  684.  
  685. cairo_bool_t
  686. _cairo_matrix_is_identity (const cairo_matrix_t *matrix)
  687. {
  688.     return (matrix->xx == 1.0 && matrix->yx == 0.0 &&
  689.             matrix->xy == 0.0 && matrix->yy == 1.0 &&
  690.             matrix->x0 == 0.0 && matrix->y0 == 0.0);
  691. }
  692.  
  693. cairo_bool_t
  694. _cairo_matrix_is_translation (const cairo_matrix_t *matrix)
  695. {
  696.     return (matrix->xx == 1.0 && matrix->yx == 0.0 &&
  697.             matrix->xy == 0.0 && matrix->yy == 1.0);
  698. }
  699.  
  700. cairo_bool_t
  701. _cairo_matrix_is_integer_translation (const cairo_matrix_t *matrix,
  702.                                       int *itx, int *ity)
  703. {
  704.     if (_cairo_matrix_is_translation (matrix))
  705.     {
  706.         cairo_fixed_t x0_fixed = _cairo_fixed_from_double (matrix->x0);
  707.         cairo_fixed_t y0_fixed = _cairo_fixed_from_double (matrix->y0);
  708.  
  709.         if (_cairo_fixed_is_integer (x0_fixed) &&
  710.             _cairo_fixed_is_integer (y0_fixed))
  711.         {
  712.             if (itx)
  713.                 *itx = _cairo_fixed_integer_part (x0_fixed);
  714.             if (ity)
  715.                 *ity = _cairo_fixed_integer_part (y0_fixed);
  716.  
  717.             return TRUE;
  718.         }
  719.     }
  720.  
  721.     return FALSE;
  722. }
  723.  
  724. cairo_bool_t
  725. _cairo_matrix_has_unity_scale (const cairo_matrix_t *matrix)
  726. {
  727.     if (matrix->xy == 0.0 && matrix->yx == 0.0) {
  728.         if (! (matrix->xx == 1.0 || matrix->xx == -1.0))
  729.             return FALSE;
  730.         if (! (matrix->yy == 1.0 || matrix->yy == -1.0))
  731.             return FALSE;
  732.     } else if (matrix->xx == 0.0 && matrix->yy == 0.0) {
  733.         if (! (matrix->xy == 1.0 || matrix->xy == -1.0))
  734.             return FALSE;
  735.         if (! (matrix->yx == 1.0 || matrix->yx == -1.0))
  736.             return FALSE;
  737.     } else
  738.         return FALSE;
  739.  
  740.     return TRUE;
  741. }
  742.  
  743. /* By pixel exact here, we mean a matrix that is composed only of
  744.  * 90 degree rotations, flips, and integer translations and produces a 1:1
  745.  * mapping between source and destination pixels. If we transform an image
  746.  * with a pixel-exact matrix, filtering is not useful.
  747.  */
  748. cairo_bool_t
  749. _cairo_matrix_is_pixel_exact (const cairo_matrix_t *matrix)
  750. {
  751.     cairo_fixed_t x0_fixed, y0_fixed;
  752.  
  753.     if (! _cairo_matrix_has_unity_scale (matrix))
  754.         return FALSE;
  755.  
  756.     x0_fixed = _cairo_fixed_from_double (matrix->x0);
  757.     y0_fixed = _cairo_fixed_from_double (matrix->y0);
  758.  
  759.     return _cairo_fixed_is_integer (x0_fixed) && _cairo_fixed_is_integer (y0_fixed);
  760. }
  761.  
  762. /*
  763.   A circle in user space is transformed into an ellipse in device space.
  764.  
  765.   The following is a derivation of a formula to calculate the length of the
  766.   major axis for this ellipse; this is useful for error bounds calculations.
  767.  
  768.   Thanks to Walter Brisken <wbrisken@aoc.nrao.edu> for this derivation:
  769.  
  770.   1.  First some notation:
  771.  
  772.   All capital letters represent vectors in two dimensions.  A prime '
  773.   represents a transformed coordinate.  Matrices are written in underlined
  774.   form, ie _R_.  Lowercase letters represent scalar real values.
  775.  
  776.   2.  The question has been posed:  What is the maximum expansion factor
  777.   achieved by the linear transformation
  778.  
  779.   X' = X _R_
  780.  
  781.   where _R_ is a real-valued 2x2 matrix with entries:
  782.  
  783.   _R_ = [a b]
  784.         [c d]  .
  785.  
  786.   In other words, what is the maximum radius, MAX[ |X'| ], reached for any
  787.   X on the unit circle ( |X| = 1 ) ?
  788.  
  789.   3.  Some useful formulae
  790.  
  791.   (A) through (C) below are standard double-angle formulae.  (D) is a lesser
  792.   known result and is derived below:
  793.  
  794.   (A)  sin²(θ) = (1 - cos(2*θ))/2
  795.   (B)  cos²(θ) = (1 + cos(2*θ))/2
  796.   (C)  sin(θ)*cos(θ) = sin(2*θ)/2
  797.   (D)  MAX[a*cos(θ) + b*sin(θ)] = sqrt(a² + b²)
  798.  
  799.   Proof of (D):
  800.  
  801.   find the maximum of the function by setting the derivative to zero:
  802.  
  803.        -a*sin(θ)+b*cos(θ) = 0
  804.  
  805.   From this it follows that
  806.  
  807.        tan(θ) = b/a
  808.  
  809.   and hence
  810.  
  811.        sin(θ) = b/sqrt(a² + b²)
  812.  
  813.   and
  814.  
  815.        cos(θ) = a/sqrt(a² + b²)
  816.  
  817.   Thus the maximum value is
  818.  
  819.        MAX[a*cos(θ) + b*sin(θ)] = (a² + b²)/sqrt(a² + b²)
  820.                                    = sqrt(a² + b²)
  821.  
  822.   4.  Derivation of maximum expansion
  823.  
  824.   To find MAX[ |X'| ] we search brute force method using calculus.  The unit
  825.   circle on which X is constrained is to be parameterized by t:
  826.  
  827.        X(θ) = (cos(θ), sin(θ))
  828.  
  829.   Thus
  830.  
  831.        X'(θ) = X(θ) * _R_ = (cos(θ), sin(θ)) * [a b]
  832.                                                [c d]
  833.              = (a*cos(θ) + c*sin(θ), b*cos(θ) + d*sin(θ)).
  834.  
  835.   Define
  836.  
  837.        r(θ) = |X'(θ)|
  838.  
  839.   Thus
  840.  
  841.        r²(θ) = (a*cos(θ) + c*sin(θ))² + (b*cos(θ) + d*sin(θ))²
  842.              = (a² + b²)*cos²(θ) + (c² + d²)*sin²(θ)
  843.                  + 2*(a*c + b*d)*cos(θ)*sin(θ)
  844.  
  845.   Now apply the double angle formulae (A) to (C) from above:
  846.  
  847.        r²(θ) = (a² + b² + c² + d²)/2
  848.              + (a² + b² - c² - d²)*cos(2*θ)/2
  849.              + (a*c + b*d)*sin(2*θ)
  850.              = f + g*cos(φ) + h*sin(φ)
  851.  
  852.   Where
  853.  
  854.        f = (a² + b² + c² + d²)/2
  855.        g = (a² + b² - c² - d²)/2
  856.        h = (a*c + d*d)
  857.        φ = 2*θ
  858.  
  859.   It is clear that MAX[ |X'| ] = sqrt(MAX[ r² ]).  Here we determine MAX[ r² ]
  860.   using (D) from above:
  861.  
  862.        MAX[ r² ] = f + sqrt(g² + h²)
  863.  
  864.   And finally
  865.  
  866.        MAX[ |X'| ] = sqrt( f + sqrt(g² + h²) )
  867.  
  868.   Which is the solution to this problem.
  869.  
  870.   Walter Brisken
  871.   2004/10/08
  872.  
  873.   (Note that the minor axis length is at the minimum of the above solution,
  874.   which is just sqrt ( f - sqrt(g² + h²) ) given the symmetry of (D)).
  875.  
  876.  
  877.   For another derivation of the same result, using Singular Value Decomposition,
  878.   see doc/tutorial/src/singular.c.
  879. */
  880.  
  881. /* determine the length of the major axis of a circle of the given radius
  882.    after applying the transformation matrix. */
  883. double
  884. _cairo_matrix_transformed_circle_major_axis (const cairo_matrix_t *matrix,
  885.                                              double radius)
  886. {
  887.     double  a, b, c, d, f, g, h, i, j;
  888.  
  889.     _cairo_matrix_get_affine (matrix,
  890.                               &a, &b,
  891.                               &c, &d,
  892.                               NULL, NULL);
  893.  
  894.     i = a*a + b*b;
  895.     j = c*c + d*d;
  896.  
  897.     f = 0.5 * (i + j);
  898.     g = 0.5 * (i - j);
  899.     h = a*c + b*d;
  900.  
  901.     return radius * sqrt (f + hypot (g, h));
  902.  
  903.     /*
  904.      * we don't need the minor axis length, which is
  905.      * double min = radius * sqrt (f - sqrt (g*g+h*h));
  906.      */
  907. }
  908.  
  909. void
  910. _cairo_matrix_to_pixman_matrix (const cairo_matrix_t    *matrix,
  911.                                 pixman_transform_t      *pixman_transform,
  912.                                 double xc,
  913.                                 double yc)
  914. {
  915.     static const pixman_transform_t pixman_identity_transform = {{
  916.         {1 << 16,        0,       0},
  917.         {       0, 1 << 16,       0},
  918.         {       0,       0, 1 << 16}
  919.     }};
  920.  
  921.     if (_cairo_matrix_is_identity (matrix)) {
  922.         *pixman_transform = pixman_identity_transform;
  923.     } else {
  924.         cairo_matrix_t inv;
  925.         unsigned max_iterations;
  926.  
  927.         pixman_transform->matrix[0][0] = _cairo_fixed_16_16_from_double (matrix->xx);
  928.         pixman_transform->matrix[0][1] = _cairo_fixed_16_16_from_double (matrix->xy);
  929.         pixman_transform->matrix[0][2] = _cairo_fixed_16_16_from_double (matrix->x0);
  930.  
  931.         pixman_transform->matrix[1][0] = _cairo_fixed_16_16_from_double (matrix->yx);
  932.         pixman_transform->matrix[1][1] = _cairo_fixed_16_16_from_double (matrix->yy);
  933.         pixman_transform->matrix[1][2] = _cairo_fixed_16_16_from_double (matrix->y0);
  934.  
  935.         pixman_transform->matrix[2][0] = 0;
  936.         pixman_transform->matrix[2][1] = 0;
  937.         pixman_transform->matrix[2][2] = 1 << 16;
  938.  
  939.         /* The conversion above breaks cairo's translation invariance:
  940.          * a translation of (a, b) in device space translates to
  941.          * a translation of (xx * a + xy * b, yx * a + yy * b)
  942.          * for cairo, while pixman uses rounded versions of xx ... yy.
  943.          * This error increases as a and b get larger.
  944.          *
  945.          * To compensate for this, we fix the point (xc, yc) in pattern
  946.          * space and adjust pixman's transform to agree with cairo's at
  947.          * that point.
  948.          */
  949.  
  950.         if (_cairo_matrix_has_unity_scale (matrix))
  951.             return;
  952.  
  953.         /* Note: If we can't invert the transformation, skip the adjustment. */
  954.         inv = *matrix;
  955.         if (cairo_matrix_invert (&inv) != CAIRO_STATUS_SUCCESS)
  956.             return;
  957.  
  958.         /* find the pattern space coordinate that maps to (xc, yc) */
  959.         xc += .5; yc += .5; /* offset for the pixel centre */
  960.         max_iterations = 5;
  961.         do {
  962.             double x,y;
  963.             pixman_vector_t vector;
  964.             cairo_fixed_16_16_t dx, dy;
  965.  
  966.             vector.vector[0] = _cairo_fixed_16_16_from_double (xc);
  967.             vector.vector[1] = _cairo_fixed_16_16_from_double (yc);
  968.             vector.vector[2] = 1 << 16;
  969.  
  970.             if (! pixman_transform_point_3d (pixman_transform, &vector))
  971.                 return;
  972.  
  973.             x = pixman_fixed_to_double (vector.vector[0]);
  974.             y = pixman_fixed_to_double (vector.vector[1]);
  975.             cairo_matrix_transform_point (&inv, &x, &y);
  976.  
  977.             /* Ideally, the vector should now be (xc, yc).
  978.              * We can now compensate for the resulting error.
  979.              */
  980.             x -= xc;
  981.             y -= yc;
  982.             cairo_matrix_transform_distance (matrix, &x, &y);
  983.             dx = _cairo_fixed_16_16_from_double (x);
  984.             dy = _cairo_fixed_16_16_from_double (y);
  985.             pixman_transform->matrix[0][2] -= dx;
  986.             pixman_transform->matrix[1][2] -= dy;
  987.  
  988.             if (dx == 0 && dy == 0)
  989.                 break;
  990.         } while (--max_iterations);
  991.     }
  992. }
  993.