gfx/cairo/libpixman/src/pixman-matrix.c

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     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  */
    23 /*
    24  * Matrix interfaces
    25  */
    27 #ifdef HAVE_CONFIG_H
    28 #include <config.h>
    29 #endif
    31 #include <math.h>
    32 #include <string.h>
    33 #include "pixman-private.h"
    35 #define F(x)    pixman_int_to_fixed (x)
    37 static force_inline int
    38 count_leading_zeros (uint32_t x)
    39 {
    40 #ifdef __GNUC__
    41     return __builtin_clz (x);
    42 #else
    43     int n = 0;
    44     while (x)
    45     {
    46         n++;
    47         x >>= 1;
    48     }
    49     return 32 - n;
    50 #endif
    51 }
    53 /*
    54  * Large signed/unsigned integer division with rounding for the platforms with
    55  * only 64-bit integer data type supported (no 128-bit data type).
    56  *
    57  * Arguments:
    58  *     hi, lo - high and low 64-bit parts of the dividend
    59  *     div    - 48-bit divisor
    60  *
    61  * Returns: lowest 64 bits of the result as a return value and highest 64
    62  *          bits of the result to "result_hi" pointer
    63  */
    65 /* grade-school unsigned division (128-bit by 48-bit) with rounding to nearest */
    66 static force_inline uint64_t
    67 rounded_udiv_128_by_48 (uint64_t  hi,
    68                         uint64_t  lo,
    69                         uint64_t  div,
    70                         uint64_t *result_hi)
    71 {
    72     uint64_t tmp, remainder, result_lo;
    73     assert(div < ((uint64_t)1 << 48));
    75     remainder = hi % div;
    76     *result_hi = hi / div;
    78     tmp = (remainder << 16) + (lo >> 48);
    79     result_lo = tmp / div;
    80     remainder = tmp % div;
    82     tmp = (remainder << 16) + ((lo >> 32) & 0xFFFF);
    83     result_lo = (result_lo << 16) + (tmp / div);
    84     remainder = tmp % div;
    86     tmp = (remainder << 16) + ((lo >> 16) & 0xFFFF);
    87     result_lo = (result_lo << 16) + (tmp / div);
    88     remainder = tmp % div;
    90     tmp = (remainder << 16) + (lo & 0xFFFF);
    91     result_lo = (result_lo << 16) + (tmp / div);
    92     remainder = tmp % div;
    94     /* round to nearest */
    95     if (remainder * 2 >= div && ++result_lo == 0)
    96         *result_hi += 1;
    98     return result_lo;
    99 }
   101 /* signed division (128-bit by 49-bit) with rounding to nearest */
   102 static inline int64_t
   103 rounded_sdiv_128_by_49 (int64_t   hi,
   104                         uint64_t  lo,
   105                         int64_t   div,
   106                         int64_t  *signed_result_hi)
   107 {
   108     uint64_t result_lo, result_hi;
   109     int sign = 0;
   110     if (div < 0)
   111     {
   112         div = -div;
   113         sign ^= 1;
   114     }
   115     if (hi < 0)
   116     {
   117         if (lo != 0)
   118             hi++;
   119         hi = -hi;
   120         lo = -lo;
   121         sign ^= 1;
   122     }
   123     result_lo = rounded_udiv_128_by_48 (hi, lo, div, &result_hi);
   124     if (sign)
   125     {
   126         if (result_lo != 0)
   127             result_hi++;
   128         result_hi = -result_hi;
   129         result_lo = -result_lo;
   130     }
   131     if (signed_result_hi)
   132     {
   133         *signed_result_hi = result_hi;
   134     }
   135     return result_lo;
   136 }
   138 /*
   139  * Multiply 64.16 fixed point value by (2^scalebits) and convert
   140  * to 128-bit integer.
   141  */
   142 static force_inline void
   143 fixed_64_16_to_int128 (int64_t  hi,
   144                        int64_t  lo,
   145                        int64_t *rhi,
   146                        int64_t *rlo,
   147                        int      scalebits)
   148 {
   149     /* separate integer and fractional parts */
   150     hi += lo >> 16;
   151     lo &= 0xFFFF;
   153     if (scalebits <= 0)
   154     {
   155         *rlo = hi >> (-scalebits);
   156         *rhi = *rlo >> 63;
   157     }
   158     else
   159     {
   160         *rhi = hi >> (64 - scalebits);
   161         *rlo = (uint64_t)hi << scalebits;
   162         if (scalebits < 16)
   163             *rlo += lo >> (16 - scalebits);
   164         else
   165             *rlo += lo << (scalebits - 16);
   166     }
   167 }
   169 /*
   170  * Convert 112.16 fixed point value to 48.16 with clamping for the out
   171  * of range values.
   172  */
   173 static force_inline pixman_fixed_48_16_t
   174 fixed_112_16_to_fixed_48_16 (int64_t hi, int64_t lo, pixman_bool_t *clampflag)
   175 {
   176     if ((lo >> 63) != hi)
   177     {
   178         *clampflag = TRUE;
   179         return hi >= 0 ? INT64_MAX : INT64_MIN;
   180     }
   181     else
   182     {
   183         return lo;
   184     }
   185 }
   187 /*
   188  * Transform a point with 31.16 fixed point coordinates from the destination
   189  * space to a point with 48.16 fixed point coordinates in the source space.
   190  * No overflows are possible for affine transformations and the results are
   191  * accurate including the least significant bit. Projective transformations
   192  * may overflow, in this case the results are just clamped to return maximum
   193  * or minimum 48.16 values (so that the caller can at least handle the NONE
   194  * and PAD repeats correctly) and the return value is FALSE to indicate that
   195  * such clamping has happened.
   196  */
   197 PIXMAN_EXPORT pixman_bool_t
   198 pixman_transform_point_31_16 (const pixman_transform_t    *t,
   199                               const pixman_vector_48_16_t *v,
   200                               pixman_vector_48_16_t       *result)
   201 {
   202     pixman_bool_t clampflag = FALSE;
   203     int i;
   204     int64_t tmp[3][2], divint;
   205     uint16_t divfrac;
   207     /* input vector values must have no more than 31 bits (including sign)
   208      * in the integer part */
   209     assert (v->v[0] <   ((pixman_fixed_48_16_t)1 << (30 + 16)));
   210     assert (v->v[0] >= -((pixman_fixed_48_16_t)1 << (30 + 16)));
   211     assert (v->v[1] <   ((pixman_fixed_48_16_t)1 << (30 + 16)));
   212     assert (v->v[1] >= -((pixman_fixed_48_16_t)1 << (30 + 16)));
   213     assert (v->v[2] <   ((pixman_fixed_48_16_t)1 << (30 + 16)));
   214     assert (v->v[2] >= -((pixman_fixed_48_16_t)1 << (30 + 16)));
   216     for (i = 0; i < 3; i++)
   217     {
   218         tmp[i][0] = (int64_t)t->matrix[i][0] * (v->v[0] >> 16);
   219         tmp[i][1] = (int64_t)t->matrix[i][0] * (v->v[0] & 0xFFFF);
   220         tmp[i][0] += (int64_t)t->matrix[i][1] * (v->v[1] >> 16);
   221         tmp[i][1] += (int64_t)t->matrix[i][1] * (v->v[1] & 0xFFFF);
   222         tmp[i][0] += (int64_t)t->matrix[i][2] * (v->v[2] >> 16);
   223         tmp[i][1] += (int64_t)t->matrix[i][2] * (v->v[2] & 0xFFFF);
   224     }
   226     /*
   227      * separate 64-bit integer and 16-bit fractional parts for the divisor,
   228      * which is also scaled by 65536 after fixed point multiplication.
   229      */
   230     divint  = tmp[2][0] + (tmp[2][1] >> 16);
   231     divfrac = tmp[2][1] & 0xFFFF;
   233     if (divint == pixman_fixed_1 && divfrac == 0)
   234     {
   235         /*
   236          * this is a simple affine transformation
   237          */
   238         result->v[0] = tmp[0][0] + ((tmp[0][1] + 0x8000) >> 16);
   239         result->v[1] = tmp[1][0] + ((tmp[1][1] + 0x8000) >> 16);
   240         result->v[2] = pixman_fixed_1;
   241     }
   242     else if (divint == 0 && divfrac == 0)
   243     {
   244         /*
   245          * handle zero divisor (if the values are non-zero, set the
   246          * results to maximum positive or minimum negative)
   247          */
   248         clampflag = TRUE;
   250         result->v[0] = tmp[0][0] + ((tmp[0][1] + 0x8000) >> 16);
   251         result->v[1] = tmp[1][0] + ((tmp[1][1] + 0x8000) >> 16);
   253         if (result->v[0] > 0)
   254             result->v[0] = INT64_MAX;
   255         else if (result->v[0] < 0)
   256             result->v[0] = INT64_MIN;
   258         if (result->v[1] > 0)
   259             result->v[1] = INT64_MAX;
   260         else if (result->v[1] < 0)
   261             result->v[1] = INT64_MIN;
   262     }
   263     else
   264     {
   265         /*
   266          * projective transformation, analyze the top 32 bits of the divisor
   267          */
   268         int32_t hi32divbits = divint >> 32;
   269         if (hi32divbits < 0)
   270             hi32divbits = ~hi32divbits;
   272         if (hi32divbits == 0)
   273         {
   274             /* the divisor is small, we can actually keep all the bits */
   275             int64_t hi, rhi, lo, rlo;
   276             int64_t div = (divint << 16) + divfrac;
   278             fixed_64_16_to_int128 (tmp[0][0], tmp[0][1], &hi, &lo, 32);
   279             rlo = rounded_sdiv_128_by_49 (hi, lo, div, &rhi);
   280             result->v[0] = fixed_112_16_to_fixed_48_16 (rhi, rlo, &clampflag);
   282             fixed_64_16_to_int128 (tmp[1][0], tmp[1][1], &hi, &lo, 32);
   283             rlo = rounded_sdiv_128_by_49 (hi, lo, div, &rhi);
   284             result->v[1] = fixed_112_16_to_fixed_48_16 (rhi, rlo, &clampflag);
   285         }
   286         else
   287         {
   288             /* the divisor needs to be reduced to 48 bits */
   289             int64_t hi, rhi, lo, rlo, div;
   290             int shift = 32 - count_leading_zeros (hi32divbits);
   291             fixed_64_16_to_int128 (divint, divfrac, &hi, &div, 16 - shift);
   293             fixed_64_16_to_int128 (tmp[0][0], tmp[0][1], &hi, &lo, 32 - shift);
   294             rlo = rounded_sdiv_128_by_49 (hi, lo, div, &rhi);
   295             result->v[0] = fixed_112_16_to_fixed_48_16 (rhi, rlo, &clampflag);
   297             fixed_64_16_to_int128 (tmp[1][0], tmp[1][1], &hi, &lo, 32 - shift);
   298             rlo = rounded_sdiv_128_by_49 (hi, lo, div, &rhi);
   299             result->v[1] = fixed_112_16_to_fixed_48_16 (rhi, rlo, &clampflag);
   300         }
   301     }
   302     result->v[2] = pixman_fixed_1;
   303     return !clampflag;
   304 }
   306 PIXMAN_EXPORT void
   307 pixman_transform_point_31_16_affine (const pixman_transform_t    *t,
   308                                      const pixman_vector_48_16_t *v,
   309                                      pixman_vector_48_16_t       *result)
   310 {
   311     int64_t hi0, lo0, hi1, lo1;
   313     /* input vector values must have no more than 31 bits (including sign)
   314      * in the integer part */
   315     assert (v->v[0] <   ((pixman_fixed_48_16_t)1 << (30 + 16)));
   316     assert (v->v[0] >= -((pixman_fixed_48_16_t)1 << (30 + 16)));
   317     assert (v->v[1] <   ((pixman_fixed_48_16_t)1 << (30 + 16)));
   318     assert (v->v[1] >= -((pixman_fixed_48_16_t)1 << (30 + 16)));
   320     hi0  = (int64_t)t->matrix[0][0] * (v->v[0] >> 16);
   321     lo0  = (int64_t)t->matrix[0][0] * (v->v[0] & 0xFFFF);
   322     hi0 += (int64_t)t->matrix[0][1] * (v->v[1] >> 16);
   323     lo0 += (int64_t)t->matrix[0][1] * (v->v[1] & 0xFFFF);
   324     hi0 += (int64_t)t->matrix[0][2];
   326     hi1  = (int64_t)t->matrix[1][0] * (v->v[0] >> 16);
   327     lo1  = (int64_t)t->matrix[1][0] * (v->v[0] & 0xFFFF);
   328     hi1 += (int64_t)t->matrix[1][1] * (v->v[1] >> 16);
   329     lo1 += (int64_t)t->matrix[1][1] * (v->v[1] & 0xFFFF);
   330     hi1 += (int64_t)t->matrix[1][2];
   332     result->v[0] = hi0 + ((lo0 + 0x8000) >> 16);
   333     result->v[1] = hi1 + ((lo1 + 0x8000) >> 16);
   334     result->v[2] = pixman_fixed_1;
   335 }
   337 PIXMAN_EXPORT void
   338 pixman_transform_point_31_16_3d (const pixman_transform_t    *t,
   339                                  const pixman_vector_48_16_t *v,
   340                                  pixman_vector_48_16_t       *result)
   341 {
   342     int i;
   343     int64_t tmp[3][2];
   345     /* input vector values must have no more than 31 bits (including sign)
   346      * in the integer part */
   347     assert (v->v[0] <   ((pixman_fixed_48_16_t)1 << (30 + 16)));
   348     assert (v->v[0] >= -((pixman_fixed_48_16_t)1 << (30 + 16)));
   349     assert (v->v[1] <   ((pixman_fixed_48_16_t)1 << (30 + 16)));
   350     assert (v->v[1] >= -((pixman_fixed_48_16_t)1 << (30 + 16)));
   351     assert (v->v[2] <   ((pixman_fixed_48_16_t)1 << (30 + 16)));
   352     assert (v->v[2] >= -((pixman_fixed_48_16_t)1 << (30 + 16)));
   354     for (i = 0; i < 3; i++)
   355     {
   356         tmp[i][0] = (int64_t)t->matrix[i][0] * (v->v[0] >> 16);
   357         tmp[i][1] = (int64_t)t->matrix[i][0] * (v->v[0] & 0xFFFF);
   358         tmp[i][0] += (int64_t)t->matrix[i][1] * (v->v[1] >> 16);
   359         tmp[i][1] += (int64_t)t->matrix[i][1] * (v->v[1] & 0xFFFF);
   360         tmp[i][0] += (int64_t)t->matrix[i][2] * (v->v[2] >> 16);
   361         tmp[i][1] += (int64_t)t->matrix[i][2] * (v->v[2] & 0xFFFF);
   362     }
   364     result->v[0] = tmp[0][0] + ((tmp[0][1] + 0x8000) >> 16);
   365     result->v[1] = tmp[1][0] + ((tmp[1][1] + 0x8000) >> 16);
   366     result->v[2] = tmp[2][0] + ((tmp[2][1] + 0x8000) >> 16);
   367 }
   369 PIXMAN_EXPORT void
   370 pixman_transform_init_identity (struct pixman_transform *matrix)
   371 {
   372     int i;
   374     memset (matrix, '\0', sizeof (struct pixman_transform));
   375     for (i = 0; i < 3; i++)
   376 	matrix->matrix[i][i] = F (1);
   377 }
   379 typedef pixman_fixed_32_32_t pixman_fixed_34_30_t;
   381 PIXMAN_EXPORT pixman_bool_t
   382 pixman_transform_point_3d (const struct pixman_transform *transform,
   383                            struct pixman_vector *         vector)
   384 {
   385     pixman_vector_48_16_t tmp;
   386     tmp.v[0] = vector->vector[0];
   387     tmp.v[1] = vector->vector[1];
   388     tmp.v[2] = vector->vector[2];
   390     pixman_transform_point_31_16_3d (transform, &tmp, &tmp);
   392     vector->vector[0] = tmp.v[0];
   393     vector->vector[1] = tmp.v[1];
   394     vector->vector[2] = tmp.v[2];
   396     return vector->vector[0] == tmp.v[0] &&
   397            vector->vector[1] == tmp.v[1] &&
   398            vector->vector[2] == tmp.v[2];
   399 }
   401 PIXMAN_EXPORT pixman_bool_t
   402 pixman_transform_point (const struct pixman_transform *transform,
   403                         struct pixman_vector *         vector)
   404 {
   405     pixman_vector_48_16_t tmp;
   406     tmp.v[0] = vector->vector[0];
   407     tmp.v[1] = vector->vector[1];
   408     tmp.v[2] = vector->vector[2];
   410     if (!pixman_transform_point_31_16 (transform, &tmp, &tmp))
   411         return FALSE;
   413     vector->vector[0] = tmp.v[0];
   414     vector->vector[1] = tmp.v[1];
   415     vector->vector[2] = tmp.v[2];
   417     return vector->vector[0] == tmp.v[0] &&
   418            vector->vector[1] == tmp.v[1] &&
   419            vector->vector[2] == tmp.v[2];
   420 }
   422 PIXMAN_EXPORT pixman_bool_t
   423 pixman_transform_multiply (struct pixman_transform *      dst,
   424                            const struct pixman_transform *l,
   425                            const struct pixman_transform *r)
   426 {
   427     struct pixman_transform d;
   428     int dx, dy;
   429     int o;
   431     for (dy = 0; dy < 3; dy++)
   432     {
   433 	for (dx = 0; dx < 3; dx++)
   434 	{
   435 	    pixman_fixed_48_16_t v;
   436 	    pixman_fixed_32_32_t partial;
   438 	    v = 0;
   439 	    for (o = 0; o < 3; o++)
   440 	    {
   441 		partial =
   442 		    (pixman_fixed_32_32_t) l->matrix[dy][o] *
   443 		    (pixman_fixed_32_32_t) r->matrix[o][dx];
   445 		v += (partial + 0x8000) >> 16;
   446 	    }
   448 	    if (v > pixman_max_fixed_48_16 || v < pixman_min_fixed_48_16)
   449 		return FALSE;
   451 	    d.matrix[dy][dx] = (pixman_fixed_t) v;
   452 	}
   453     }
   455     *dst = d;
   456     return TRUE;
   457 }
   459 PIXMAN_EXPORT void
   460 pixman_transform_init_scale (struct pixman_transform *t,
   461                              pixman_fixed_t           sx,
   462                              pixman_fixed_t           sy)
   463 {
   464     memset (t, '\0', sizeof (struct pixman_transform));
   466     t->matrix[0][0] = sx;
   467     t->matrix[1][1] = sy;
   468     t->matrix[2][2] = F (1);
   469 }
   471 static pixman_fixed_t
   472 fixed_inverse (pixman_fixed_t x)
   473 {
   474     return (pixman_fixed_t) ((((pixman_fixed_48_16_t) F (1)) * F (1)) / x);
   475 }
   477 PIXMAN_EXPORT pixman_bool_t
   478 pixman_transform_scale (struct pixman_transform *forward,
   479                         struct pixman_transform *reverse,
   480                         pixman_fixed_t           sx,
   481                         pixman_fixed_t           sy)
   482 {
   483     struct pixman_transform t;
   485     if (sx == 0 || sy == 0)
   486 	return FALSE;
   488     if (forward)
   489     {
   490 	pixman_transform_init_scale (&t, sx, sy);
   491 	if (!pixman_transform_multiply (forward, &t, forward))
   492 	    return FALSE;
   493     }
   495     if (reverse)
   496     {
   497 	pixman_transform_init_scale (&t, fixed_inverse (sx),
   498 	                             fixed_inverse (sy));
   499 	if (!pixman_transform_multiply (reverse, reverse, &t))
   500 	    return FALSE;
   501     }
   503     return TRUE;
   504 }
   506 PIXMAN_EXPORT void
   507 pixman_transform_init_rotate (struct pixman_transform *t,
   508                               pixman_fixed_t           c,
   509                               pixman_fixed_t           s)
   510 {
   511     memset (t, '\0', sizeof (struct pixman_transform));
   513     t->matrix[0][0] = c;
   514     t->matrix[0][1] = -s;
   515     t->matrix[1][0] = s;
   516     t->matrix[1][1] = c;
   517     t->matrix[2][2] = F (1);
   518 }
   520 PIXMAN_EXPORT pixman_bool_t
   521 pixman_transform_rotate (struct pixman_transform *forward,
   522                          struct pixman_transform *reverse,
   523                          pixman_fixed_t           c,
   524                          pixman_fixed_t           s)
   525 {
   526     struct pixman_transform t;
   528     if (forward)
   529     {
   530 	pixman_transform_init_rotate (&t, c, s);
   531 	if (!pixman_transform_multiply (forward, &t, forward))
   532 	    return FALSE;
   533     }
   535     if (reverse)
   536     {
   537 	pixman_transform_init_rotate (&t, c, -s);
   538 	if (!pixman_transform_multiply (reverse, reverse, &t))
   539 	    return FALSE;
   540     }
   542     return TRUE;
   543 }
   545 PIXMAN_EXPORT void
   546 pixman_transform_init_translate (struct pixman_transform *t,
   547                                  pixman_fixed_t           tx,
   548                                  pixman_fixed_t           ty)
   549 {
   550     memset (t, '\0', sizeof (struct pixman_transform));
   552     t->matrix[0][0] = F (1);
   553     t->matrix[0][2] = tx;
   554     t->matrix[1][1] = F (1);
   555     t->matrix[1][2] = ty;
   556     t->matrix[2][2] = F (1);
   557 }
   559 PIXMAN_EXPORT pixman_bool_t
   560 pixman_transform_translate (struct pixman_transform *forward,
   561                             struct pixman_transform *reverse,
   562                             pixman_fixed_t           tx,
   563                             pixman_fixed_t           ty)
   564 {
   565     struct pixman_transform t;
   567     if (forward)
   568     {
   569 	pixman_transform_init_translate (&t, tx, ty);
   571 	if (!pixman_transform_multiply (forward, &t, forward))
   572 	    return FALSE;
   573     }
   575     if (reverse)
   576     {
   577 	pixman_transform_init_translate (&t, -tx, -ty);
   579 	if (!pixman_transform_multiply (reverse, reverse, &t))
   580 	    return FALSE;
   581     }
   582     return TRUE;
   583 }
   585 PIXMAN_EXPORT pixman_bool_t
   586 pixman_transform_bounds (const struct pixman_transform *matrix,
   587                          struct pixman_box16 *          b)
   589 {
   590     struct pixman_vector v[4];
   591     int i;
   592     int x1, y1, x2, y2;
   594     v[0].vector[0] = F (b->x1);
   595     v[0].vector[1] = F (b->y1);
   596     v[0].vector[2] = F (1);
   598     v[1].vector[0] = F (b->x2);
   599     v[1].vector[1] = F (b->y1);
   600     v[1].vector[2] = F (1);
   602     v[2].vector[0] = F (b->x2);
   603     v[2].vector[1] = F (b->y2);
   604     v[2].vector[2] = F (1);
   606     v[3].vector[0] = F (b->x1);
   607     v[3].vector[1] = F (b->y2);
   608     v[3].vector[2] = F (1);
   610     for (i = 0; i < 4; i++)
   611     {
   612 	if (!pixman_transform_point (matrix, &v[i]))
   613 	    return FALSE;
   615 	x1 = pixman_fixed_to_int (v[i].vector[0]);
   616 	y1 = pixman_fixed_to_int (v[i].vector[1]);
   617 	x2 = pixman_fixed_to_int (pixman_fixed_ceil (v[i].vector[0]));
   618 	y2 = pixman_fixed_to_int (pixman_fixed_ceil (v[i].vector[1]));
   620 	if (i == 0)
   621 	{
   622 	    b->x1 = x1;
   623 	    b->y1 = y1;
   624 	    b->x2 = x2;
   625 	    b->y2 = y2;
   626 	}
   627 	else
   628 	{
   629 	    if (x1 < b->x1) b->x1 = x1;
   630 	    if (y1 < b->y1) b->y1 = y1;
   631 	    if (x2 > b->x2) b->x2 = x2;
   632 	    if (y2 > b->y2) b->y2 = y2;
   633 	}
   634     }
   636     return TRUE;
   637 }
   639 PIXMAN_EXPORT pixman_bool_t
   640 pixman_transform_invert (struct pixman_transform *      dst,
   641                          const struct pixman_transform *src)
   642 {
   643     struct pixman_f_transform m;
   645     pixman_f_transform_from_pixman_transform (&m, src);
   647     if (!pixman_f_transform_invert (&m, &m))
   648 	return FALSE;
   650     if (!pixman_transform_from_pixman_f_transform (dst, &m))
   651 	return FALSE;
   653     return TRUE;
   654 }
   656 static pixman_bool_t
   657 within_epsilon (pixman_fixed_t a,
   658                 pixman_fixed_t b,
   659                 pixman_fixed_t epsilon)
   660 {
   661     pixman_fixed_t t = a - b;
   663     if (t < 0)
   664 	t = -t;
   666     return t <= epsilon;
   667 }
   669 #define EPSILON (pixman_fixed_t) (2)
   671 #define IS_SAME(a, b) (within_epsilon (a, b, EPSILON))
   672 #define IS_ZERO(a)    (within_epsilon (a, 0, EPSILON))
   673 #define IS_ONE(a)     (within_epsilon (a, F (1), EPSILON))
   674 #define IS_UNIT(a)			    \
   675     (within_epsilon (a, F (1), EPSILON) ||  \
   676      within_epsilon (a, F (-1), EPSILON) || \
   677      IS_ZERO (a))
   678 #define IS_INT(a)    (IS_ZERO (pixman_fixed_frac (a)))
   680 PIXMAN_EXPORT pixman_bool_t
   681 pixman_transform_is_identity (const struct pixman_transform *t)
   682 {
   683     return (IS_SAME (t->matrix[0][0], t->matrix[1][1]) &&
   684 	    IS_SAME (t->matrix[0][0], t->matrix[2][2]) &&
   685 	    !IS_ZERO (t->matrix[0][0]) &&
   686 	    IS_ZERO (t->matrix[0][1]) &&
   687 	    IS_ZERO (t->matrix[0][2]) &&
   688 	    IS_ZERO (t->matrix[1][0]) &&
   689 	    IS_ZERO (t->matrix[1][2]) &&
   690 	    IS_ZERO (t->matrix[2][0]) &&
   691 	    IS_ZERO (t->matrix[2][1]));
   692 }
   694 PIXMAN_EXPORT pixman_bool_t
   695 pixman_transform_is_scale (const struct pixman_transform *t)
   696 {
   697     return (!IS_ZERO (t->matrix[0][0]) &&
   698             IS_ZERO (t->matrix[0][1]) &&
   699             IS_ZERO (t->matrix[0][2]) &&
   701             IS_ZERO (t->matrix[1][0]) &&
   702             !IS_ZERO (t->matrix[1][1]) &&
   703             IS_ZERO (t->matrix[1][2]) &&
   705             IS_ZERO (t->matrix[2][0]) &&
   706             IS_ZERO (t->matrix[2][1]) &&
   707             !IS_ZERO (t->matrix[2][2]));
   708 }
   710 PIXMAN_EXPORT pixman_bool_t
   711 pixman_transform_is_int_translate (const struct pixman_transform *t)
   712 {
   713     return (IS_ONE (t->matrix[0][0]) &&
   714             IS_ZERO (t->matrix[0][1]) &&
   715             IS_INT (t->matrix[0][2]) &&
   717             IS_ZERO (t->matrix[1][0]) &&
   718             IS_ONE (t->matrix[1][1]) &&
   719             IS_INT (t->matrix[1][2]) &&
   721             IS_ZERO (t->matrix[2][0]) &&
   722             IS_ZERO (t->matrix[2][1]) &&
   723             IS_ONE (t->matrix[2][2]));
   724 }
   726 PIXMAN_EXPORT pixman_bool_t
   727 pixman_transform_is_inverse (const struct pixman_transform *a,
   728                              const struct pixman_transform *b)
   729 {
   730     struct pixman_transform t;
   732     if (!pixman_transform_multiply (&t, a, b))
   733 	return FALSE;
   735     return pixman_transform_is_identity (&t);
   736 }
   738 PIXMAN_EXPORT void
   739 pixman_f_transform_from_pixman_transform (struct pixman_f_transform *    ft,
   740                                           const struct pixman_transform *t)
   741 {
   742     int i, j;
   744     for (j = 0; j < 3; j++)
   745     {
   746 	for (i = 0; i < 3; i++)
   747 	    ft->m[j][i] = pixman_fixed_to_double (t->matrix[j][i]);
   748     }
   749 }
   751 PIXMAN_EXPORT pixman_bool_t
   752 pixman_transform_from_pixman_f_transform (struct pixman_transform *        t,
   753                                           const struct pixman_f_transform *ft)
   754 {
   755     int i, j;
   757     for (j = 0; j < 3; j++)
   758     {
   759 	for (i = 0; i < 3; i++)
   760 	{
   761 	    double d = ft->m[j][i];
   762 	    if (d < -32767.0 || d > 32767.0)
   763 		return FALSE;
   764 	    d = d * 65536.0 + 0.5;
   765 	    t->matrix[j][i] = (pixman_fixed_t) floor (d);
   766 	}
   767     }
   769     return TRUE;
   770 }
   772 PIXMAN_EXPORT pixman_bool_t
   773 pixman_f_transform_invert (struct pixman_f_transform *      dst,
   774                            const struct pixman_f_transform *src)
   775 {
   776     static const int a[3] = { 2, 2, 1 };
   777     static const int b[3] = { 1, 0, 0 };
   778     pixman_f_transform_t d;
   779     double det;
   780     int i, j;
   782     det = 0;
   783     for (i = 0; i < 3; i++)
   784     {
   785 	double p;
   786 	int ai = a[i];
   787 	int bi = b[i];
   788 	p = src->m[i][0] * (src->m[ai][2] * src->m[bi][1] -
   789 	                    src->m[ai][1] * src->m[bi][2]);
   790 	if (i == 1)
   791 	    p = -p;
   792 	det += p;
   793     }
   795     if (det == 0)
   796 	return FALSE;
   798     det = 1 / det;
   799     for (j = 0; j < 3; j++)
   800     {
   801 	for (i = 0; i < 3; i++)
   802 	{
   803 	    double p;
   804 	    int ai = a[i];
   805 	    int aj = a[j];
   806 	    int bi = b[i];
   807 	    int bj = b[j];
   809 	    p = (src->m[ai][aj] * src->m[bi][bj] -
   810 	         src->m[ai][bj] * src->m[bi][aj]);
   812 	    if (((i + j) & 1) != 0)
   813 		p = -p;
   815 	    d.m[j][i] = det * p;
   816 	}
   817     }
   819     *dst = d;
   821     return TRUE;
   822 }
   824 PIXMAN_EXPORT pixman_bool_t
   825 pixman_f_transform_point (const struct pixman_f_transform *t,
   826                           struct pixman_f_vector *         v)
   827 {
   828     struct pixman_f_vector result;
   829     int i, j;
   830     double a;
   832     for (j = 0; j < 3; j++)
   833     {
   834 	a = 0;
   835 	for (i = 0; i < 3; i++)
   836 	    a += t->m[j][i] * v->v[i];
   837 	result.v[j] = a;
   838     }
   840     if (!result.v[2])
   841 	return FALSE;
   843     for (j = 0; j < 2; j++)
   844 	v->v[j] = result.v[j] / result.v[2];
   846     v->v[2] = 1;
   848     return TRUE;
   849 }
   851 PIXMAN_EXPORT void
   852 pixman_f_transform_point_3d (const struct pixman_f_transform *t,
   853                              struct pixman_f_vector *         v)
   854 {
   855     struct pixman_f_vector result;
   856     int i, j;
   857     double a;
   859     for (j = 0; j < 3; j++)
   860     {
   861 	a = 0;
   862 	for (i = 0; i < 3; i++)
   863 	    a += t->m[j][i] * v->v[i];
   864 	result.v[j] = a;
   865     }
   867     *v = result;
   868 }
   870 PIXMAN_EXPORT void
   871 pixman_f_transform_multiply (struct pixman_f_transform *      dst,
   872                              const struct pixman_f_transform *l,
   873                              const struct pixman_f_transform *r)
   874 {
   875     struct pixman_f_transform d;
   876     int dx, dy;
   877     int o;
   879     for (dy = 0; dy < 3; dy++)
   880     {
   881 	for (dx = 0; dx < 3; dx++)
   882 	{
   883 	    double v = 0;
   884 	    for (o = 0; o < 3; o++)
   885 		v += l->m[dy][o] * r->m[o][dx];
   886 	    d.m[dy][dx] = v;
   887 	}
   888     }
   890     *dst = d;
   891 }
   893 PIXMAN_EXPORT void
   894 pixman_f_transform_init_scale (struct pixman_f_transform *t,
   895                                double                     sx,
   896                                double                     sy)
   897 {
   898     t->m[0][0] = sx;
   899     t->m[0][1] = 0;
   900     t->m[0][2] = 0;
   901     t->m[1][0] = 0;
   902     t->m[1][1] = sy;
   903     t->m[1][2] = 0;
   904     t->m[2][0] = 0;
   905     t->m[2][1] = 0;
   906     t->m[2][2] = 1;
   907 }
   909 PIXMAN_EXPORT pixman_bool_t
   910 pixman_f_transform_scale (struct pixman_f_transform *forward,
   911                           struct pixman_f_transform *reverse,
   912                           double                     sx,
   913                           double                     sy)
   914 {
   915     struct pixman_f_transform t;
   917     if (sx == 0 || sy == 0)
   918 	return FALSE;
   920     if (forward)
   921     {
   922 	pixman_f_transform_init_scale (&t, sx, sy);
   923 	pixman_f_transform_multiply (forward, &t, forward);
   924     }
   926     if (reverse)
   927     {
   928 	pixman_f_transform_init_scale (&t, 1 / sx, 1 / sy);
   929 	pixman_f_transform_multiply (reverse, reverse, &t);
   930     }
   932     return TRUE;
   933 }
   935 PIXMAN_EXPORT void
   936 pixman_f_transform_init_rotate (struct pixman_f_transform *t,
   937                                 double                     c,
   938                                 double                     s)
   939 {
   940     t->m[0][0] = c;
   941     t->m[0][1] = -s;
   942     t->m[0][2] = 0;
   943     t->m[1][0] = s;
   944     t->m[1][1] = c;
   945     t->m[1][2] = 0;
   946     t->m[2][0] = 0;
   947     t->m[2][1] = 0;
   948     t->m[2][2] = 1;
   949 }
   951 PIXMAN_EXPORT pixman_bool_t
   952 pixman_f_transform_rotate (struct pixman_f_transform *forward,
   953                            struct pixman_f_transform *reverse,
   954                            double                     c,
   955                            double                     s)
   956 {
   957     struct pixman_f_transform t;
   959     if (forward)
   960     {
   961 	pixman_f_transform_init_rotate (&t, c, s);
   962 	pixman_f_transform_multiply (forward, &t, forward);
   963     }
   965     if (reverse)
   966     {
   967 	pixman_f_transform_init_rotate (&t, c, -s);
   968 	pixman_f_transform_multiply (reverse, reverse, &t);
   969     }
   971     return TRUE;
   972 }
   974 PIXMAN_EXPORT void
   975 pixman_f_transform_init_translate (struct pixman_f_transform *t,
   976                                    double                     tx,
   977                                    double                     ty)
   978 {
   979     t->m[0][0] = 1;
   980     t->m[0][1] = 0;
   981     t->m[0][2] = tx;
   982     t->m[1][0] = 0;
   983     t->m[1][1] = 1;
   984     t->m[1][2] = ty;
   985     t->m[2][0] = 0;
   986     t->m[2][1] = 0;
   987     t->m[2][2] = 1;
   988 }
   990 PIXMAN_EXPORT pixman_bool_t
   991 pixman_f_transform_translate (struct pixman_f_transform *forward,
   992                               struct pixman_f_transform *reverse,
   993                               double                     tx,
   994                               double                     ty)
   995 {
   996     struct pixman_f_transform t;
   998     if (forward)
   999     {
  1000 	pixman_f_transform_init_translate (&t, tx, ty);
  1001 	pixman_f_transform_multiply (forward, &t, forward);
  1004     if (reverse)
  1006 	pixman_f_transform_init_translate (&t, -tx, -ty);
  1007 	pixman_f_transform_multiply (reverse, reverse, &t);
  1010     return TRUE;
  1013 PIXMAN_EXPORT pixman_bool_t
  1014 pixman_f_transform_bounds (const struct pixman_f_transform *t,
  1015                            struct pixman_box16 *            b)
  1017     struct pixman_f_vector v[4];
  1018     int i;
  1019     int x1, y1, x2, y2;
  1021     v[0].v[0] = b->x1;
  1022     v[0].v[1] = b->y1;
  1023     v[0].v[2] = 1;
  1024     v[1].v[0] = b->x2;
  1025     v[1].v[1] = b->y1;
  1026     v[1].v[2] = 1;
  1027     v[2].v[0] = b->x2;
  1028     v[2].v[1] = b->y2;
  1029     v[2].v[2] = 1;
  1030     v[3].v[0] = b->x1;
  1031     v[3].v[1] = b->y2;
  1032     v[3].v[2] = 1;
  1034     for (i = 0; i < 4; i++)
  1036 	if (!pixman_f_transform_point (t, &v[i]))
  1037 	    return FALSE;
  1039 	x1 = floor (v[i].v[0]);
  1040 	y1 = floor (v[i].v[1]);
  1041 	x2 = ceil (v[i].v[0]);
  1042 	y2 = ceil (v[i].v[1]);
  1044 	if (i == 0)
  1046 	    b->x1 = x1;
  1047 	    b->y1 = y1;
  1048 	    b->x2 = x2;
  1049 	    b->y2 = y2;
  1051 	else
  1053 	    if (x1 < b->x1) b->x1 = x1;
  1054 	    if (y1 < b->y1) b->y1 = y1;
  1055 	    if (x2 > b->x2) b->x2 = x2;
  1056 	    if (y2 > b->y2) b->y2 = y2;
  1060     return TRUE;
  1063 PIXMAN_EXPORT void
  1064 pixman_f_transform_init_identity (struct pixman_f_transform *t)
  1066     int i, j;
  1068     for (j = 0; j < 3; j++)
  1070 	for (i = 0; i < 3; i++)
  1071 	    t->m[j][i] = i == j ? 1 : 0;

mercurial