Subversion Repositories Kolibri OS

Rev

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

  1. /*
  2.  * Copyright © 2008 Keith Packard
  3.  *
  4.  * Permission to use, copy, modify, distribute, and sell this software and its
  5.  * documentation for any purpose is hereby granted without fee, provided that
  6.  * the above copyright notice appear in all copies and that both that copyright
  7.  * notice and this permission notice appear in supporting documentation, and
  8.  * that the name of the copyright holders not be used in advertising or
  9.  * publicity pertaining to distribution of the software without specific,
  10.  * written prior permission.  The copyright holders make no representations
  11.  * about the suitability of this software for any purpose.  It is provided "as
  12.  * is" without express or implied warranty.
  13.  *
  14.  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  15.  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
  16.  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  17.  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
  18.  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  19.  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
  20.  * OF THIS SOFTWARE.
  21.  */
  22.  
  23. /*
  24.  * Matrix interfaces
  25.  */
  26.  
  27. #ifdef HAVE_CONFIG_H
  28. #include "config.h"
  29. #endif
  30.  
  31. #include <math.h>
  32. #include <string.h>
  33. #include "pixman-private.h"
  34.  
  35. #define F(x)    pixman_int_to_fixed (x)
  36.  
  37. PIXMAN_EXPORT void
  38. pixman_transform_init_identity (struct pixman_transform *matrix)
  39. {
  40.     int i;
  41.  
  42.     memset (matrix, '\0', sizeof (struct pixman_transform));
  43.     for (i = 0; i < 3; i++)
  44.         matrix->matrix[i][i] = F (1);
  45. }
  46.  
  47. typedef pixman_fixed_32_32_t pixman_fixed_34_30_t;
  48.  
  49. PIXMAN_EXPORT pixman_bool_t
  50. pixman_transform_point_3d (const struct pixman_transform *transform,
  51.                            struct pixman_vector *         vector)
  52. {
  53.     struct pixman_vector result;
  54.     pixman_fixed_32_32_t partial;
  55.     pixman_fixed_48_16_t v;
  56.     int i, j;
  57.  
  58.     for (j = 0; j < 3; j++)
  59.     {
  60.         v = 0;
  61.         for (i = 0; i < 3; i++)
  62.         {
  63.             partial = ((pixman_fixed_48_16_t) transform->matrix[j][i] *
  64.                        (pixman_fixed_48_16_t) vector->vector[i]);
  65.             v += partial >> 16;
  66.         }
  67.        
  68.         if (v > pixman_max_fixed_48_16 || v < pixman_min_fixed_48_16)
  69.             return FALSE;
  70.        
  71.         result.vector[j] = (pixman_fixed_t) v;
  72.     }
  73.    
  74.     *vector = result;
  75.  
  76.     if (!result.vector[2])
  77.         return FALSE;
  78.  
  79.     return TRUE;
  80. }
  81.  
  82. PIXMAN_EXPORT pixman_bool_t
  83. pixman_transform_point (const struct pixman_transform *transform,
  84.                         struct pixman_vector *         vector)
  85. {
  86.     pixman_fixed_32_32_t partial;
  87.     pixman_fixed_34_30_t v[3];
  88.     pixman_fixed_48_16_t quo;
  89.     int i, j;
  90.  
  91.     for (j = 0; j < 3; j++)
  92.     {
  93.         v[j] = 0;
  94.        
  95.         for (i = 0; i < 3; i++)
  96.         {
  97.             partial = ((pixman_fixed_32_32_t) transform->matrix[j][i] *
  98.                        (pixman_fixed_32_32_t) vector->vector[i]);
  99.             v[j] += partial >> 2;
  100.         }
  101.     }
  102.    
  103.     if (!(v[2] >> 16))
  104.         return FALSE;
  105.  
  106.     for (j = 0; j < 2; j++)
  107.     {
  108.         quo = v[j] / (v[2] >> 16);
  109.         if (quo > pixman_max_fixed_48_16 || quo < pixman_min_fixed_48_16)
  110.             return FALSE;
  111.         vector->vector[j] = (pixman_fixed_t) quo;
  112.     }
  113.    
  114.     vector->vector[2] = pixman_fixed_1;
  115.     return TRUE;
  116. }
  117.  
  118. PIXMAN_EXPORT pixman_bool_t
  119. pixman_transform_multiply (struct pixman_transform *      dst,
  120.                            const struct pixman_transform *l,
  121.                            const struct pixman_transform *r)
  122. {
  123.     struct pixman_transform d;
  124.     int dx, dy;
  125.     int o;
  126.  
  127.     for (dy = 0; dy < 3; dy++)
  128.     {
  129.         for (dx = 0; dx < 3; dx++)
  130.         {
  131.             pixman_fixed_48_16_t v;
  132.             pixman_fixed_32_32_t partial;
  133.            
  134.             v = 0;
  135.             for (o = 0; o < 3; o++)
  136.             {
  137.                 partial =
  138.                     (pixman_fixed_32_32_t) l->matrix[dy][o] *
  139.                     (pixman_fixed_32_32_t) r->matrix[o][dx];
  140.  
  141.                 v += partial >> 16;
  142.             }
  143.  
  144.             if (v > pixman_max_fixed_48_16 || v < pixman_min_fixed_48_16)
  145.                 return FALSE;
  146.            
  147.             d.matrix[dy][dx] = (pixman_fixed_t) v;
  148.         }
  149.     }
  150.  
  151.     *dst = d;
  152.     return TRUE;
  153. }
  154.  
  155. PIXMAN_EXPORT void
  156. pixman_transform_init_scale (struct pixman_transform *t,
  157.                              pixman_fixed_t           sx,
  158.                              pixman_fixed_t           sy)
  159. {
  160.     memset (t, '\0', sizeof (struct pixman_transform));
  161.  
  162.     t->matrix[0][0] = sx;
  163.     t->matrix[1][1] = sy;
  164.     t->matrix[2][2] = F (1);
  165. }
  166.  
  167. static pixman_fixed_t
  168. fixed_inverse (pixman_fixed_t x)
  169. {
  170.     return (pixman_fixed_t) ((((pixman_fixed_48_16_t) F (1)) * F (1)) / x);
  171. }
  172.  
  173. PIXMAN_EXPORT pixman_bool_t
  174. pixman_transform_scale (struct pixman_transform *forward,
  175.                         struct pixman_transform *reverse,
  176.                         pixman_fixed_t           sx,
  177.                         pixman_fixed_t           sy)
  178. {
  179.     struct pixman_transform t;
  180.  
  181.     if (sx == 0 || sy == 0)
  182.         return FALSE;
  183.  
  184.     if (forward)
  185.     {
  186.         pixman_transform_init_scale (&t, sx, sy);
  187.         if (!pixman_transform_multiply (forward, &t, forward))
  188.             return FALSE;
  189.     }
  190.    
  191.     if (reverse)
  192.     {
  193.         pixman_transform_init_scale (&t, fixed_inverse (sx),
  194.                                      fixed_inverse (sy));
  195.         if (!pixman_transform_multiply (reverse, reverse, &t))
  196.             return FALSE;
  197.     }
  198.    
  199.     return TRUE;
  200. }
  201.  
  202. PIXMAN_EXPORT void
  203. pixman_transform_init_rotate (struct pixman_transform *t,
  204.                               pixman_fixed_t           c,
  205.                               pixman_fixed_t           s)
  206. {
  207.     memset (t, '\0', sizeof (struct pixman_transform));
  208.  
  209.     t->matrix[0][0] = c;
  210.     t->matrix[0][1] = -s;
  211.     t->matrix[1][0] = s;
  212.     t->matrix[1][1] = c;
  213.     t->matrix[2][2] = F (1);
  214. }
  215.  
  216. PIXMAN_EXPORT pixman_bool_t
  217. pixman_transform_rotate (struct pixman_transform *forward,
  218.                          struct pixman_transform *reverse,
  219.                          pixman_fixed_t           c,
  220.                          pixman_fixed_t           s)
  221. {
  222.     struct pixman_transform t;
  223.  
  224.     if (forward)
  225.     {
  226.         pixman_transform_init_rotate (&t, c, s);
  227.         if (!pixman_transform_multiply (forward, &t, forward))
  228.             return FALSE;
  229.     }
  230.  
  231.     if (reverse)
  232.     {
  233.         pixman_transform_init_rotate (&t, c, -s);
  234.         if (!pixman_transform_multiply (reverse, reverse, &t))
  235.             return FALSE;
  236.     }
  237.    
  238.     return TRUE;
  239. }
  240.  
  241. PIXMAN_EXPORT void
  242. pixman_transform_init_translate (struct pixman_transform *t,
  243.                                  pixman_fixed_t           tx,
  244.                                  pixman_fixed_t           ty)
  245. {
  246.     memset (t, '\0', sizeof (struct pixman_transform));
  247.  
  248.     t->matrix[0][0] = F (1);
  249.     t->matrix[0][2] = tx;
  250.     t->matrix[1][1] = F (1);
  251.     t->matrix[1][2] = ty;
  252.     t->matrix[2][2] = F (1);
  253. }
  254.  
  255. PIXMAN_EXPORT pixman_bool_t
  256. pixman_transform_translate (struct pixman_transform *forward,
  257.                             struct pixman_transform *reverse,
  258.                             pixman_fixed_t           tx,
  259.                             pixman_fixed_t           ty)
  260. {
  261.     struct pixman_transform t;
  262.  
  263.     if (forward)
  264.     {
  265.         pixman_transform_init_translate (&t, tx, ty);
  266.  
  267.         if (!pixman_transform_multiply (forward, &t, forward))
  268.             return FALSE;
  269.     }
  270.  
  271.     if (reverse)
  272.     {
  273.         pixman_transform_init_translate (&t, -tx, -ty);
  274.  
  275.         if (!pixman_transform_multiply (reverse, reverse, &t))
  276.             return FALSE;
  277.     }
  278.     return TRUE;
  279. }
  280.  
  281. PIXMAN_EXPORT pixman_bool_t
  282. pixman_transform_bounds (const struct pixman_transform *matrix,
  283.                          struct pixman_box16 *          b)
  284.  
  285. {
  286.     struct pixman_vector v[4];
  287.     int i;
  288.     int x1, y1, x2, y2;
  289.  
  290.     v[0].vector[0] = F (b->x1);
  291.     v[0].vector[1] = F (b->y1);
  292.     v[0].vector[2] = F (1);
  293.  
  294.     v[1].vector[0] = F (b->x2);
  295.     v[1].vector[1] = F (b->y1);
  296.     v[1].vector[2] = F (1);
  297.  
  298.     v[2].vector[0] = F (b->x2);
  299.     v[2].vector[1] = F (b->y2);
  300.     v[2].vector[2] = F (1);
  301.  
  302.     v[3].vector[0] = F (b->x1);
  303.     v[3].vector[1] = F (b->y2);
  304.     v[3].vector[2] = F (1);
  305.  
  306.     for (i = 0; i < 4; i++)
  307.     {
  308.         if (!pixman_transform_point (matrix, &v[i]))
  309.             return FALSE;
  310.  
  311.         x1 = pixman_fixed_to_int (v[i].vector[0]);
  312.         y1 = pixman_fixed_to_int (v[i].vector[1]);
  313.         x2 = pixman_fixed_to_int (pixman_fixed_ceil (v[i].vector[0]));
  314.         y2 = pixman_fixed_to_int (pixman_fixed_ceil (v[i].vector[1]));
  315.  
  316.         if (i == 0)
  317.         {
  318.             b->x1 = x1;
  319.             b->y1 = y1;
  320.             b->x2 = x2;
  321.             b->y2 = y2;
  322.         }
  323.         else
  324.         {
  325.             if (x1 < b->x1) b->x1 = x1;
  326.             if (y1 < b->y1) b->y1 = y1;
  327.             if (x2 > b->x2) b->x2 = x2;
  328.             if (y2 > b->y2) b->y2 = y2;
  329.         }
  330.     }
  331.  
  332.     return TRUE;
  333. }
  334.  
  335. PIXMAN_EXPORT pixman_bool_t
  336. pixman_transform_invert (struct pixman_transform *      dst,
  337.                          const struct pixman_transform *src)
  338. {
  339.     struct pixman_f_transform m, r;
  340.  
  341.     pixman_f_transform_from_pixman_transform (&m, src);
  342.  
  343.     if (!pixman_f_transform_invert (&r, &m))
  344.         return FALSE;
  345.  
  346.     if (!pixman_transform_from_pixman_f_transform (dst, &r))
  347.         return FALSE;
  348.  
  349.     return TRUE;
  350. }
  351.  
  352. static pixman_bool_t
  353. within_epsilon (pixman_fixed_t a,
  354.                 pixman_fixed_t b,
  355.                 pixman_fixed_t epsilon)
  356. {
  357.     pixman_fixed_t t = a - b;
  358.  
  359.     if (t < 0)
  360.         t = -t;
  361.  
  362.     return t <= epsilon;
  363. }
  364.  
  365. #define EPSILON (pixman_fixed_t) (2)
  366.  
  367. #define IS_SAME(a, b) (within_epsilon (a, b, EPSILON))
  368. #define IS_ZERO(a)    (within_epsilon (a, 0, EPSILON))
  369. #define IS_ONE(a)     (within_epsilon (a, F (1), EPSILON))
  370. #define IS_UNIT(a)                          \
  371.     (within_epsilon (a, F (1), EPSILON) ||  \
  372.      within_epsilon (a, F (-1), EPSILON) || \
  373.      IS_ZERO (a))
  374. #define IS_INT(a)    (IS_ZERO (pixman_fixed_frac (a)))
  375.  
  376. PIXMAN_EXPORT pixman_bool_t
  377. pixman_transform_is_identity (const struct pixman_transform *t)
  378. {
  379.     return (IS_SAME (t->matrix[0][0], t->matrix[1][1]) &&
  380.             IS_SAME (t->matrix[0][0], t->matrix[2][2]) &&
  381.             !IS_ZERO (t->matrix[0][0]) &&
  382.             IS_ZERO (t->matrix[0][1]) &&
  383.             IS_ZERO (t->matrix[0][2]) &&
  384.             IS_ZERO (t->matrix[1][0]) &&
  385.             IS_ZERO (t->matrix[1][2]) &&
  386.             IS_ZERO (t->matrix[2][0]) &&
  387.             IS_ZERO (t->matrix[2][1]));
  388. }
  389.  
  390. PIXMAN_EXPORT pixman_bool_t
  391. pixman_transform_is_scale (const struct pixman_transform *t)
  392. {
  393.     return (!IS_ZERO (t->matrix[0][0]) &&
  394.             IS_ZERO (t->matrix[0][1]) &&
  395.             IS_ZERO (t->matrix[0][2]) &&
  396.  
  397.             IS_ZERO (t->matrix[1][0]) &&
  398.             !IS_ZERO (t->matrix[1][1]) &&
  399.             IS_ZERO (t->matrix[1][2]) &&
  400.  
  401.             IS_ZERO (t->matrix[2][0]) &&
  402.             IS_ZERO (t->matrix[2][1]) &&
  403.             !IS_ZERO (t->matrix[2][2]));
  404. }
  405.  
  406. PIXMAN_EXPORT pixman_bool_t
  407. pixman_transform_is_int_translate (const struct pixman_transform *t)
  408. {
  409.     return (IS_ONE (t->matrix[0][0]) &&
  410.             IS_ZERO (t->matrix[0][1]) &&
  411.             IS_INT (t->matrix[0][2]) &&
  412.  
  413.             IS_ZERO (t->matrix[1][0]) &&
  414.             IS_ONE (t->matrix[1][1]) &&
  415.             IS_INT (t->matrix[1][2]) &&
  416.  
  417.             IS_ZERO (t->matrix[2][0]) &&
  418.             IS_ZERO (t->matrix[2][1]) &&
  419.             IS_ONE (t->matrix[2][2]));
  420. }
  421.  
  422. PIXMAN_EXPORT pixman_bool_t
  423. pixman_transform_is_inverse (const struct pixman_transform *a,
  424.                              const struct pixman_transform *b)
  425. {
  426.     struct pixman_transform t;
  427.  
  428.     pixman_transform_multiply (&t, a, b);
  429.  
  430.     return pixman_transform_is_identity (&t);
  431. }
  432.  
  433. PIXMAN_EXPORT void
  434. pixman_f_transform_from_pixman_transform (struct pixman_f_transform *    ft,
  435.                                           const struct pixman_transform *t)
  436. {
  437.     int i, j;
  438.  
  439.     for (j = 0; j < 3; j++)
  440.     {
  441.         for (i = 0; i < 3; i++)
  442.             ft->m[j][i] = pixman_fixed_to_double (t->matrix[j][i]);
  443.     }
  444. }
  445.  
  446. PIXMAN_EXPORT pixman_bool_t
  447. pixman_transform_from_pixman_f_transform (struct pixman_transform *        t,
  448.                                           const struct pixman_f_transform *ft)
  449. {
  450.     int i, j;
  451.  
  452.     for (j = 0; j < 3; j++)
  453.     {
  454.         for (i = 0; i < 3; i++)
  455.         {
  456.             double d = ft->m[j][i];
  457.             if (d < -32767.0 || d > 32767.0)
  458.                 return FALSE;
  459.             d = d * 65536.0 + 0.5;
  460.             t->matrix[j][i] = (pixman_fixed_t) floor (d);
  461.         }
  462.     }
  463.    
  464.     return TRUE;
  465. }
  466.  
  467. static const int a[3] = { 3, 3, 2 };
  468. static const int b[3] = { 2, 1, 1 };
  469.  
  470. PIXMAN_EXPORT pixman_bool_t
  471. pixman_f_transform_invert (struct pixman_f_transform *      dst,
  472.                            const struct pixman_f_transform *src)
  473. {
  474.     double det;
  475.     int i, j;
  476.     static int a[3] = { 2, 2, 1 };
  477.     static int b[3] = { 1, 0, 0 };
  478.  
  479.     det = 0;
  480.     for (i = 0; i < 3; i++)
  481.     {
  482.         double p;
  483.         int ai = a[i];
  484.         int bi = b[i];
  485.         p = src->m[i][0] * (src->m[ai][2] * src->m[bi][1] -
  486.                             src->m[ai][1] * src->m[bi][2]);
  487.         if (i == 1)
  488.             p = -p;
  489.         det += p;
  490.     }
  491.    
  492.     if (det == 0)
  493.         return FALSE;
  494.    
  495.     det = 1 / det;
  496.     for (j = 0; j < 3; j++)
  497.     {
  498.         for (i = 0; i < 3; i++)
  499.         {
  500.             double p;
  501.             int ai = a[i];
  502.             int aj = a[j];
  503.             int bi = b[i];
  504.             int bj = b[j];
  505.  
  506.             p = (src->m[ai][aj] * src->m[bi][bj] -
  507.                  src->m[ai][bj] * src->m[bi][aj]);
  508.            
  509.             if (((i + j) & 1) != 0)
  510.                 p = -p;
  511.            
  512.             dst->m[j][i] = det * p;
  513.         }
  514.     }
  515.  
  516.     return TRUE;
  517. }
  518.  
  519. PIXMAN_EXPORT pixman_bool_t
  520. pixman_f_transform_point (const struct pixman_f_transform *t,
  521.                           struct pixman_f_vector *         v)
  522. {
  523.     struct pixman_f_vector result;
  524.     int i, j;
  525.     double a;
  526.  
  527.     for (j = 0; j < 3; j++)
  528.     {
  529.         a = 0;
  530.         for (i = 0; i < 3; i++)
  531.             a += t->m[j][i] * v->v[i];
  532.         result.v[j] = a;
  533.     }
  534.    
  535.     if (!result.v[2])
  536.         return FALSE;
  537.  
  538.     for (j = 0; j < 2; j++)
  539.         v->v[j] = result.v[j] / result.v[2];
  540.  
  541.     v->v[2] = 1;
  542.  
  543.     return TRUE;
  544. }
  545.  
  546. PIXMAN_EXPORT void
  547. pixman_f_transform_point_3d (const struct pixman_f_transform *t,
  548.                              struct pixman_f_vector *         v)
  549. {
  550.     struct pixman_f_vector result;
  551.     int i, j;
  552.     double a;
  553.  
  554.     for (j = 0; j < 3; j++)
  555.     {
  556.         a = 0;
  557.         for (i = 0; i < 3; i++)
  558.             a += t->m[j][i] * v->v[i];
  559.         result.v[j] = a;
  560.     }
  561.    
  562.     *v = result;
  563. }
  564.  
  565. PIXMAN_EXPORT void
  566. pixman_f_transform_multiply (struct pixman_f_transform *      dst,
  567.                              const struct pixman_f_transform *l,
  568.                              const struct pixman_f_transform *r)
  569. {
  570.     struct pixman_f_transform d;
  571.     int dx, dy;
  572.     int o;
  573.  
  574.     for (dy = 0; dy < 3; dy++)
  575.     {
  576.         for (dx = 0; dx < 3; dx++)
  577.         {
  578.             double v = 0;
  579.             for (o = 0; o < 3; o++)
  580.                 v += l->m[dy][o] * r->m[o][dx];
  581.             d.m[dy][dx] = v;
  582.         }
  583.     }
  584.    
  585.     *dst = d;
  586. }
  587.  
  588. PIXMAN_EXPORT void
  589. pixman_f_transform_init_scale (struct pixman_f_transform *t,
  590.                                double                     sx,
  591.                                double                     sy)
  592. {
  593.     t->m[0][0] = sx;
  594.     t->m[0][1] = 0;
  595.     t->m[0][2] = 0;
  596.     t->m[1][0] = 0;
  597.     t->m[1][1] = sy;
  598.     t->m[1][2] = 0;
  599.     t->m[2][0] = 0;
  600.     t->m[2][1] = 0;
  601.     t->m[2][2] = 1;
  602. }
  603.  
  604. PIXMAN_EXPORT pixman_bool_t
  605. pixman_f_transform_scale (struct pixman_f_transform *forward,
  606.                           struct pixman_f_transform *reverse,
  607.                           double                     sx,
  608.                           double                     sy)
  609. {
  610.     struct pixman_f_transform t;
  611.  
  612.     if (sx == 0 || sy == 0)
  613.         return FALSE;
  614.  
  615.     if (forward)
  616.     {
  617.         pixman_f_transform_init_scale (&t, sx, sy);
  618.         pixman_f_transform_multiply (forward, &t, forward);
  619.     }
  620.    
  621.     if (reverse)
  622.     {
  623.         pixman_f_transform_init_scale (&t, 1 / sx, 1 / sy);
  624.         pixman_f_transform_multiply (reverse, reverse, &t);
  625.     }
  626.    
  627.     return TRUE;
  628. }
  629.  
  630. PIXMAN_EXPORT void
  631. pixman_f_transform_init_rotate (struct pixman_f_transform *t,
  632.                                 double                     c,
  633.                                 double                     s)
  634. {
  635.     t->m[0][0] = c;
  636.     t->m[0][1] = -s;
  637.     t->m[0][2] = 0;
  638.     t->m[1][0] = s;
  639.     t->m[1][1] = c;
  640.     t->m[1][2] = 0;
  641.     t->m[2][0] = 0;
  642.     t->m[2][1] = 0;
  643.     t->m[2][2] = 1;
  644. }
  645.  
  646. PIXMAN_EXPORT pixman_bool_t
  647. pixman_f_transform_rotate (struct pixman_f_transform *forward,
  648.                            struct pixman_f_transform *reverse,
  649.                            double                     c,
  650.                            double                     s)
  651. {
  652.     struct pixman_f_transform t;
  653.  
  654.     if (forward)
  655.     {
  656.         pixman_f_transform_init_rotate (&t, c, s);
  657.         pixman_f_transform_multiply (forward, &t, forward);
  658.     }
  659.    
  660.     if (reverse)
  661.     {
  662.         pixman_f_transform_init_rotate (&t, c, -s);
  663.         pixman_f_transform_multiply (reverse, reverse, &t);
  664.     }
  665.  
  666.     return TRUE;
  667. }
  668.  
  669. PIXMAN_EXPORT void
  670. pixman_f_transform_init_translate (struct pixman_f_transform *t,
  671.                                    double                     tx,
  672.                                    double                     ty)
  673. {
  674.     t->m[0][0] = 1;
  675.     t->m[0][1] = 0;
  676.     t->m[0][2] = tx;
  677.     t->m[1][0] = 0;
  678.     t->m[1][1] = 1;
  679.     t->m[1][2] = ty;
  680.     t->m[2][0] = 0;
  681.     t->m[2][1] = 0;
  682.     t->m[2][2] = 1;
  683. }
  684.  
  685. PIXMAN_EXPORT pixman_bool_t
  686. pixman_f_transform_translate (struct pixman_f_transform *forward,
  687.                               struct pixman_f_transform *reverse,
  688.                               double                     tx,
  689.                               double                     ty)
  690. {
  691.     struct pixman_f_transform t;
  692.  
  693.     if (forward)
  694.     {
  695.         pixman_f_transform_init_translate (&t, tx, ty);
  696.         pixman_f_transform_multiply (forward, &t, forward);
  697.     }
  698.  
  699.     if (reverse)
  700.     {
  701.         pixman_f_transform_init_translate (&t, -tx, -ty);
  702.         pixman_f_transform_multiply (reverse, reverse, &t);
  703.     }
  704.  
  705.     return TRUE;
  706. }
  707.  
  708. PIXMAN_EXPORT pixman_bool_t
  709. pixman_f_transform_bounds (const struct pixman_f_transform *t,
  710.                            struct pixman_box16 *            b)
  711. {
  712.     struct pixman_f_vector v[4];
  713.     int i;
  714.     int x1, y1, x2, y2;
  715.  
  716.     v[0].v[0] = b->x1;
  717.     v[0].v[1] = b->y1;
  718.     v[0].v[2] = 1;
  719.     v[1].v[0] = b->x2;
  720.     v[1].v[1] = b->y1;
  721.     v[1].v[2] = 1;
  722.     v[2].v[0] = b->x2;
  723.     v[2].v[1] = b->y2;
  724.     v[2].v[2] = 1;
  725.     v[3].v[0] = b->x1;
  726.     v[3].v[1] = b->y2;
  727.     v[3].v[2] = 1;
  728.  
  729.     for (i = 0; i < 4; i++)
  730.     {
  731.         if (!pixman_f_transform_point (t, &v[i]))
  732.             return FALSE;
  733.  
  734.         x1 = floor (v[i].v[0]);
  735.         y1 = floor (v[i].v[1]);
  736.         x2 = ceil (v[i].v[0]);
  737.         y2 = ceil (v[i].v[1]);
  738.  
  739.         if (i == 0)
  740.         {
  741.             b->x1 = x1;
  742.             b->y1 = y1;
  743.             b->x2 = x2;
  744.             b->y2 = y2;
  745.         }
  746.         else
  747.         {
  748.             if (x1 < b->x1) b->x1 = x1;
  749.             if (y1 < b->y1) b->y1 = y1;
  750.             if (x2 > b->x2) b->x2 = x2;
  751.             if (y2 > b->y2) b->y2 = y2;
  752.         }
  753.     }
  754.  
  755.     return TRUE;
  756. }
  757.  
  758. PIXMAN_EXPORT void
  759. pixman_f_transform_init_identity (struct pixman_f_transform *t)
  760. {
  761.     int i, j;
  762.  
  763.     for (j = 0; j < 3; j++)
  764.     {
  765.         for (i = 0; i < 3; i++)
  766.             t->m[j][i] = i == j ? 1 : 0;
  767.     }
  768. }
  769.