Use MAKE_ACCESSORS() to generate accessors for the a1 format.
[profile/ivi/pixman.git] / pixman / pixman-matrix.c
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     if (!pixman_transform_multiply (&t, a, b))
429         return FALSE;
430
431     return pixman_transform_is_identity (&t);
432 }
433
434 PIXMAN_EXPORT void
435 pixman_f_transform_from_pixman_transform (struct pixman_f_transform *    ft,
436                                           const struct pixman_transform *t)
437 {
438     int i, j;
439
440     for (j = 0; j < 3; j++)
441     {
442         for (i = 0; i < 3; i++)
443             ft->m[j][i] = pixman_fixed_to_double (t->matrix[j][i]);
444     }
445 }
446
447 PIXMAN_EXPORT pixman_bool_t
448 pixman_transform_from_pixman_f_transform (struct pixman_transform *        t,
449                                           const struct pixman_f_transform *ft)
450 {
451     int i, j;
452
453     for (j = 0; j < 3; j++)
454     {
455         for (i = 0; i < 3; i++)
456         {
457             double d = ft->m[j][i];
458             if (d < -32767.0 || d > 32767.0)
459                 return FALSE;
460             d = d * 65536.0 + 0.5;
461             t->matrix[j][i] = (pixman_fixed_t) floor (d);
462         }
463     }
464     
465     return TRUE;
466 }
467
468 PIXMAN_EXPORT pixman_bool_t
469 pixman_f_transform_invert (struct pixman_f_transform *      dst,
470                            const struct pixman_f_transform *src)
471 {
472     double det;
473     int i, j;
474     static int a[3] = { 2, 2, 1 };
475     static int b[3] = { 1, 0, 0 };
476
477     det = 0;
478     for (i = 0; i < 3; i++)
479     {
480         double p;
481         int ai = a[i];
482         int bi = b[i];
483         p = src->m[i][0] * (src->m[ai][2] * src->m[bi][1] -
484                             src->m[ai][1] * src->m[bi][2]);
485         if (i == 1)
486             p = -p;
487         det += p;
488     }
489     
490     if (det == 0)
491         return FALSE;
492     
493     det = 1 / det;
494     for (j = 0; j < 3; j++)
495     {
496         for (i = 0; i < 3; i++)
497         {
498             double p;
499             int ai = a[i];
500             int aj = a[j];
501             int bi = b[i];
502             int bj = b[j];
503
504             p = (src->m[ai][aj] * src->m[bi][bj] -
505                  src->m[ai][bj] * src->m[bi][aj]);
506             
507             if (((i + j) & 1) != 0)
508                 p = -p;
509             
510             dst->m[j][i] = det * p;
511         }
512     }
513
514     return TRUE;
515 }
516
517 PIXMAN_EXPORT pixman_bool_t
518 pixman_f_transform_point (const struct pixman_f_transform *t,
519                           struct pixman_f_vector *         v)
520 {
521     struct pixman_f_vector result;
522     int i, j;
523     double a;
524
525     for (j = 0; j < 3; j++)
526     {
527         a = 0;
528         for (i = 0; i < 3; i++)
529             a += t->m[j][i] * v->v[i];
530         result.v[j] = a;
531     }
532     
533     if (!result.v[2])
534         return FALSE;
535
536     for (j = 0; j < 2; j++)
537         v->v[j] = result.v[j] / result.v[2];
538
539     v->v[2] = 1;
540
541     return TRUE;
542 }
543
544 PIXMAN_EXPORT void
545 pixman_f_transform_point_3d (const struct pixman_f_transform *t,
546                              struct pixman_f_vector *         v)
547 {
548     struct pixman_f_vector result;
549     int i, j;
550     double a;
551
552     for (j = 0; j < 3; j++)
553     {
554         a = 0;
555         for (i = 0; i < 3; i++)
556             a += t->m[j][i] * v->v[i];
557         result.v[j] = a;
558     }
559     
560     *v = result;
561 }
562
563 PIXMAN_EXPORT void
564 pixman_f_transform_multiply (struct pixman_f_transform *      dst,
565                              const struct pixman_f_transform *l,
566                              const struct pixman_f_transform *r)
567 {
568     struct pixman_f_transform d;
569     int dx, dy;
570     int o;
571
572     for (dy = 0; dy < 3; dy++)
573     {
574         for (dx = 0; dx < 3; dx++)
575         {
576             double v = 0;
577             for (o = 0; o < 3; o++)
578                 v += l->m[dy][o] * r->m[o][dx];
579             d.m[dy][dx] = v;
580         }
581     }
582     
583     *dst = d;
584 }
585
586 PIXMAN_EXPORT void
587 pixman_f_transform_init_scale (struct pixman_f_transform *t,
588                                double                     sx,
589                                double                     sy)
590 {
591     t->m[0][0] = sx;
592     t->m[0][1] = 0;
593     t->m[0][2] = 0;
594     t->m[1][0] = 0;
595     t->m[1][1] = sy;
596     t->m[1][2] = 0;
597     t->m[2][0] = 0;
598     t->m[2][1] = 0;
599     t->m[2][2] = 1;
600 }
601
602 PIXMAN_EXPORT pixman_bool_t
603 pixman_f_transform_scale (struct pixman_f_transform *forward,
604                           struct pixman_f_transform *reverse,
605                           double                     sx,
606                           double                     sy)
607 {
608     struct pixman_f_transform t;
609
610     if (sx == 0 || sy == 0)
611         return FALSE;
612
613     if (forward)
614     {
615         pixman_f_transform_init_scale (&t, sx, sy);
616         pixman_f_transform_multiply (forward, &t, forward);
617     }
618     
619     if (reverse)
620     {
621         pixman_f_transform_init_scale (&t, 1 / sx, 1 / sy);
622         pixman_f_transform_multiply (reverse, reverse, &t);
623     }
624     
625     return TRUE;
626 }
627
628 PIXMAN_EXPORT void
629 pixman_f_transform_init_rotate (struct pixman_f_transform *t,
630                                 double                     c,
631                                 double                     s)
632 {
633     t->m[0][0] = c;
634     t->m[0][1] = -s;
635     t->m[0][2] = 0;
636     t->m[1][0] = s;
637     t->m[1][1] = c;
638     t->m[1][2] = 0;
639     t->m[2][0] = 0;
640     t->m[2][1] = 0;
641     t->m[2][2] = 1;
642 }
643
644 PIXMAN_EXPORT pixman_bool_t
645 pixman_f_transform_rotate (struct pixman_f_transform *forward,
646                            struct pixman_f_transform *reverse,
647                            double                     c,
648                            double                     s)
649 {
650     struct pixman_f_transform t;
651
652     if (forward)
653     {
654         pixman_f_transform_init_rotate (&t, c, s);
655         pixman_f_transform_multiply (forward, &t, forward);
656     }
657     
658     if (reverse)
659     {
660         pixman_f_transform_init_rotate (&t, c, -s);
661         pixman_f_transform_multiply (reverse, reverse, &t);
662     }
663
664     return TRUE;
665 }
666
667 PIXMAN_EXPORT void
668 pixman_f_transform_init_translate (struct pixman_f_transform *t,
669                                    double                     tx,
670                                    double                     ty)
671 {
672     t->m[0][0] = 1;
673     t->m[0][1] = 0;
674     t->m[0][2] = tx;
675     t->m[1][0] = 0;
676     t->m[1][1] = 1;
677     t->m[1][2] = ty;
678     t->m[2][0] = 0;
679     t->m[2][1] = 0;
680     t->m[2][2] = 1;
681 }
682
683 PIXMAN_EXPORT pixman_bool_t
684 pixman_f_transform_translate (struct pixman_f_transform *forward,
685                               struct pixman_f_transform *reverse,
686                               double                     tx,
687                               double                     ty)
688 {
689     struct pixman_f_transform t;
690
691     if (forward)
692     {
693         pixman_f_transform_init_translate (&t, tx, ty);
694         pixman_f_transform_multiply (forward, &t, forward);
695     }
696
697     if (reverse)
698     {
699         pixman_f_transform_init_translate (&t, -tx, -ty);
700         pixman_f_transform_multiply (reverse, reverse, &t);
701     }
702
703     return TRUE;
704 }
705
706 PIXMAN_EXPORT pixman_bool_t
707 pixman_f_transform_bounds (const struct pixman_f_transform *t,
708                            struct pixman_box16 *            b)
709 {
710     struct pixman_f_vector v[4];
711     int i;
712     int x1, y1, x2, y2;
713
714     v[0].v[0] = b->x1;
715     v[0].v[1] = b->y1;
716     v[0].v[2] = 1;
717     v[1].v[0] = b->x2;
718     v[1].v[1] = b->y1;
719     v[1].v[2] = 1;
720     v[2].v[0] = b->x2;
721     v[2].v[1] = b->y2;
722     v[2].v[2] = 1;
723     v[3].v[0] = b->x1;
724     v[3].v[1] = b->y2;
725     v[3].v[2] = 1;
726
727     for (i = 0; i < 4; i++)
728     {
729         if (!pixman_f_transform_point (t, &v[i]))
730             return FALSE;
731
732         x1 = floor (v[i].v[0]);
733         y1 = floor (v[i].v[1]);
734         x2 = ceil (v[i].v[0]);
735         y2 = ceil (v[i].v[1]);
736
737         if (i == 0)
738         {
739             b->x1 = x1;
740             b->y1 = y1;
741             b->x2 = x2;
742             b->y2 = y2;
743         }
744         else
745         {
746             if (x1 < b->x1) b->x1 = x1;
747             if (y1 < b->y1) b->y1 = y1;
748             if (x2 > b->x2) b->x2 = x2;
749             if (y2 > b->y2) b->y2 = y2;
750         }
751     }
752
753     return TRUE;
754 }
755
756 PIXMAN_EXPORT void
757 pixman_f_transform_init_identity (struct pixman_f_transform *t)
758 {
759     int i, j;
760
761     for (j = 0; j < 3; j++)
762     {
763         for (i = 0; i < 3; i++)
764             t->m[j][i] = i == j ? 1 : 0;
765     }
766 }