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 0 : pixman_transform_init_identity (struct pixman_transform *matrix)
39 : {
40 : int i;
41 :
42 0 : memset (matrix, '\0', sizeof (struct pixman_transform));
43 0 : for (i = 0; i < 3; i++)
44 0 : matrix->matrix[i][i] = F (1);
45 0 : }
46 :
47 : typedef pixman_fixed_32_32_t pixman_fixed_34_30_t;
48 :
49 : PIXMAN_EXPORT pixman_bool_t
50 20 : 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 80 : for (j = 0; j < 3; j++)
59 : {
60 60 : v = 0;
61 240 : for (i = 0; i < 3; i++)
62 : {
63 360 : partial = ((pixman_fixed_48_16_t) transform->matrix[j][i] *
64 180 : (pixman_fixed_48_16_t) vector->vector[i]);
65 180 : v += partial >> 16;
66 : }
67 :
68 60 : if (v > pixman_max_fixed_48_16 || v < pixman_min_fixed_48_16)
69 0 : return FALSE;
70 :
71 60 : result.vector[j] = (pixman_fixed_t) v;
72 : }
73 :
74 20 : *vector = result;
75 :
76 20 : if (!result.vector[2])
77 0 : return FALSE;
78 :
79 20 : return TRUE;
80 : }
81 :
82 : PIXMAN_EXPORT pixman_bool_t
83 80 : 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 320 : for (j = 0; j < 3; j++)
92 : {
93 240 : v[j] = 0;
94 :
95 960 : for (i = 0; i < 3; i++)
96 : {
97 1440 : partial = ((pixman_fixed_32_32_t) transform->matrix[j][i] *
98 720 : (pixman_fixed_32_32_t) vector->vector[i]);
99 720 : v[j] += partial >> 2;
100 : }
101 : }
102 :
103 80 : if (!(v[2] >> 16))
104 0 : return FALSE;
105 :
106 240 : for (j = 0; j < 2; j++)
107 : {
108 160 : quo = v[j] / (v[2] >> 16);
109 160 : if (quo > pixman_max_fixed_48_16 || quo < pixman_min_fixed_48_16)
110 0 : return FALSE;
111 160 : vector->vector[j] = (pixman_fixed_t) quo;
112 : }
113 :
114 80 : vector->vector[2] = pixman_fixed_1;
115 80 : return TRUE;
116 : }
117 :
118 : PIXMAN_EXPORT pixman_bool_t
119 0 : 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 0 : for (dy = 0; dy < 3; dy++)
128 : {
129 0 : for (dx = 0; dx < 3; dx++)
130 : {
131 : pixman_fixed_48_16_t v;
132 : pixman_fixed_32_32_t partial;
133 :
134 0 : v = 0;
135 0 : for (o = 0; o < 3; o++)
136 : {
137 0 : partial =
138 0 : (pixman_fixed_32_32_t) l->matrix[dy][o] *
139 0 : (pixman_fixed_32_32_t) r->matrix[o][dx];
140 :
141 0 : v += partial >> 16;
142 : }
143 :
144 0 : if (v > pixman_max_fixed_48_16 || v < pixman_min_fixed_48_16)
145 0 : return FALSE;
146 :
147 0 : d.matrix[dy][dx] = (pixman_fixed_t) v;
148 : }
149 : }
150 :
151 0 : *dst = d;
152 0 : return TRUE;
153 : }
154 :
155 : PIXMAN_EXPORT void
156 0 : pixman_transform_init_scale (struct pixman_transform *t,
157 : pixman_fixed_t sx,
158 : pixman_fixed_t sy)
159 : {
160 0 : memset (t, '\0', sizeof (struct pixman_transform));
161 :
162 0 : t->matrix[0][0] = sx;
163 0 : t->matrix[1][1] = sy;
164 0 : t->matrix[2][2] = F (1);
165 0 : }
166 :
167 : static pixman_fixed_t
168 0 : fixed_inverse (pixman_fixed_t x)
169 : {
170 0 : return (pixman_fixed_t) ((((pixman_fixed_48_16_t) F (1)) * F (1)) / x);
171 : }
172 :
173 : PIXMAN_EXPORT pixman_bool_t
174 0 : 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 0 : if (sx == 0 || sy == 0)
182 0 : return FALSE;
183 :
184 0 : if (forward)
185 : {
186 0 : pixman_transform_init_scale (&t, sx, sy);
187 0 : if (!pixman_transform_multiply (forward, &t, forward))
188 0 : return FALSE;
189 : }
190 :
191 0 : if (reverse)
192 : {
193 0 : pixman_transform_init_scale (&t, fixed_inverse (sx),
194 : fixed_inverse (sy));
195 0 : if (!pixman_transform_multiply (reverse, reverse, &t))
196 0 : return FALSE;
197 : }
198 :
199 0 : return TRUE;
200 : }
201 :
202 : PIXMAN_EXPORT void
203 0 : pixman_transform_init_rotate (struct pixman_transform *t,
204 : pixman_fixed_t c,
205 : pixman_fixed_t s)
206 : {
207 0 : memset (t, '\0', sizeof (struct pixman_transform));
208 :
209 0 : t->matrix[0][0] = c;
210 0 : t->matrix[0][1] = -s;
211 0 : t->matrix[1][0] = s;
212 0 : t->matrix[1][1] = c;
213 0 : t->matrix[2][2] = F (1);
214 0 : }
215 :
216 : PIXMAN_EXPORT pixman_bool_t
217 0 : 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 0 : if (forward)
225 : {
226 0 : pixman_transform_init_rotate (&t, c, s);
227 0 : if (!pixman_transform_multiply (forward, &t, forward))
228 0 : return FALSE;
229 : }
230 :
231 0 : if (reverse)
232 : {
233 0 : pixman_transform_init_rotate (&t, c, -s);
234 0 : if (!pixman_transform_multiply (reverse, reverse, &t))
235 0 : return FALSE;
236 : }
237 :
238 0 : return TRUE;
239 : }
240 :
241 : PIXMAN_EXPORT void
242 0 : pixman_transform_init_translate (struct pixman_transform *t,
243 : pixman_fixed_t tx,
244 : pixman_fixed_t ty)
245 : {
246 0 : memset (t, '\0', sizeof (struct pixman_transform));
247 :
248 0 : t->matrix[0][0] = F (1);
249 0 : t->matrix[0][2] = tx;
250 0 : t->matrix[1][1] = F (1);
251 0 : t->matrix[1][2] = ty;
252 0 : t->matrix[2][2] = F (1);
253 0 : }
254 :
255 : PIXMAN_EXPORT pixman_bool_t
256 0 : 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 0 : if (forward)
264 : {
265 0 : pixman_transform_init_translate (&t, tx, ty);
266 :
267 0 : if (!pixman_transform_multiply (forward, &t, forward))
268 0 : return FALSE;
269 : }
270 :
271 0 : if (reverse)
272 : {
273 0 : pixman_transform_init_translate (&t, -tx, -ty);
274 :
275 0 : if (!pixman_transform_multiply (reverse, reverse, &t))
276 0 : return FALSE;
277 : }
278 0 : return TRUE;
279 : }
280 :
281 : PIXMAN_EXPORT pixman_bool_t
282 0 : 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 0 : v[0].vector[0] = F (b->x1);
291 0 : v[0].vector[1] = F (b->y1);
292 0 : v[0].vector[2] = F (1);
293 :
294 0 : v[1].vector[0] = F (b->x2);
295 0 : v[1].vector[1] = F (b->y1);
296 0 : v[1].vector[2] = F (1);
297 :
298 0 : v[2].vector[0] = F (b->x2);
299 0 : v[2].vector[1] = F (b->y2);
300 0 : v[2].vector[2] = F (1);
301 :
302 0 : v[3].vector[0] = F (b->x1);
303 0 : v[3].vector[1] = F (b->y2);
304 0 : v[3].vector[2] = F (1);
305 :
306 0 : for (i = 0; i < 4; i++)
307 : {
308 0 : if (!pixman_transform_point (matrix, &v[i]))
309 0 : return FALSE;
310 :
311 0 : x1 = pixman_fixed_to_int (v[i].vector[0]);
312 0 : y1 = pixman_fixed_to_int (v[i].vector[1]);
313 0 : x2 = pixman_fixed_to_int (pixman_fixed_ceil (v[i].vector[0]));
314 0 : y2 = pixman_fixed_to_int (pixman_fixed_ceil (v[i].vector[1]));
315 :
316 0 : if (i == 0)
317 : {
318 0 : b->x1 = x1;
319 0 : b->y1 = y1;
320 0 : b->x2 = x2;
321 0 : b->y2 = y2;
322 : }
323 : else
324 : {
325 0 : if (x1 < b->x1) b->x1 = x1;
326 0 : if (y1 < b->y1) b->y1 = y1;
327 0 : if (x2 > b->x2) b->x2 = x2;
328 0 : if (y2 > b->y2) b->y2 = y2;
329 : }
330 : }
331 :
332 0 : return TRUE;
333 : }
334 :
335 : PIXMAN_EXPORT pixman_bool_t
336 0 : pixman_transform_invert (struct pixman_transform * dst,
337 : const struct pixman_transform *src)
338 : {
339 : struct pixman_f_transform m, r;
340 :
341 0 : pixman_f_transform_from_pixman_transform (&m, src);
342 :
343 0 : if (!pixman_f_transform_invert (&r, &m))
344 0 : return FALSE;
345 :
346 0 : if (!pixman_transform_from_pixman_f_transform (dst, &r))
347 0 : return FALSE;
348 :
349 0 : return TRUE;
350 : }
351 :
352 : static pixman_bool_t
353 0 : within_epsilon (pixman_fixed_t a,
354 : pixman_fixed_t b,
355 : pixman_fixed_t epsilon)
356 : {
357 0 : pixman_fixed_t t = a - b;
358 :
359 0 : if (t < 0)
360 0 : t = -t;
361 :
362 0 : 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 0 : pixman_transform_is_identity (const struct pixman_transform *t)
378 : {
379 0 : return (IS_SAME (t->matrix[0][0], t->matrix[1][1]) &&
380 0 : IS_SAME (t->matrix[0][0], t->matrix[2][2]) &&
381 0 : !IS_ZERO (t->matrix[0][0]) &&
382 0 : IS_ZERO (t->matrix[0][1]) &&
383 0 : IS_ZERO (t->matrix[0][2]) &&
384 0 : IS_ZERO (t->matrix[1][0]) &&
385 0 : IS_ZERO (t->matrix[1][2]) &&
386 0 : IS_ZERO (t->matrix[2][0]) &&
387 0 : IS_ZERO (t->matrix[2][1]));
388 : }
389 :
390 : PIXMAN_EXPORT pixman_bool_t
391 0 : pixman_transform_is_scale (const struct pixman_transform *t)
392 : {
393 0 : return (!IS_ZERO (t->matrix[0][0]) &&
394 0 : IS_ZERO (t->matrix[0][1]) &&
395 0 : IS_ZERO (t->matrix[0][2]) &&
396 :
397 0 : IS_ZERO (t->matrix[1][0]) &&
398 0 : !IS_ZERO (t->matrix[1][1]) &&
399 0 : IS_ZERO (t->matrix[1][2]) &&
400 :
401 0 : IS_ZERO (t->matrix[2][0]) &&
402 0 : IS_ZERO (t->matrix[2][1]) &&
403 0 : !IS_ZERO (t->matrix[2][2]));
404 : }
405 :
406 : PIXMAN_EXPORT pixman_bool_t
407 0 : pixman_transform_is_int_translate (const struct pixman_transform *t)
408 : {
409 0 : return (IS_ONE (t->matrix[0][0]) &&
410 0 : IS_ZERO (t->matrix[0][1]) &&
411 0 : IS_INT (t->matrix[0][2]) &&
412 :
413 0 : IS_ZERO (t->matrix[1][0]) &&
414 0 : IS_ONE (t->matrix[1][1]) &&
415 0 : IS_INT (t->matrix[1][2]) &&
416 :
417 0 : IS_ZERO (t->matrix[2][0]) &&
418 0 : IS_ZERO (t->matrix[2][1]) &&
419 0 : IS_ONE (t->matrix[2][2]));
420 : }
421 :
422 : PIXMAN_EXPORT pixman_bool_t
423 0 : pixman_transform_is_inverse (const struct pixman_transform *a,
424 : const struct pixman_transform *b)
425 : {
426 : struct pixman_transform t;
427 :
428 0 : if (!pixman_transform_multiply (&t, a, b))
429 0 : return FALSE;
430 :
431 0 : return pixman_transform_is_identity (&t);
432 : }
433 :
434 : PIXMAN_EXPORT void
435 0 : pixman_f_transform_from_pixman_transform (struct pixman_f_transform * ft,
436 : const struct pixman_transform *t)
437 : {
438 : int i, j;
439 :
440 0 : for (j = 0; j < 3; j++)
441 : {
442 0 : for (i = 0; i < 3; i++)
443 0 : ft->m[j][i] = pixman_fixed_to_double (t->matrix[j][i]);
444 : }
445 0 : }
446 :
447 : PIXMAN_EXPORT pixman_bool_t
448 0 : pixman_transform_from_pixman_f_transform (struct pixman_transform * t,
449 : const struct pixman_f_transform *ft)
450 : {
451 : int i, j;
452 :
453 0 : for (j = 0; j < 3; j++)
454 : {
455 0 : for (i = 0; i < 3; i++)
456 : {
457 0 : double d = ft->m[j][i];
458 0 : if (d < -32767.0 || d > 32767.0)
459 0 : return FALSE;
460 0 : d = d * 65536.0 + 0.5;
461 0 : t->matrix[j][i] = (pixman_fixed_t) floor (d);
462 : }
463 : }
464 :
465 0 : return TRUE;
466 : }
467 :
468 : PIXMAN_EXPORT pixman_bool_t
469 0 : 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 0 : det = 0;
478 0 : for (i = 0; i < 3; i++)
479 : {
480 : double p;
481 0 : int ai = a[i];
482 0 : int bi = b[i];
483 0 : p = src->m[i][0] * (src->m[ai][2] * src->m[bi][1] -
484 0 : src->m[ai][1] * src->m[bi][2]);
485 0 : if (i == 1)
486 0 : p = -p;
487 0 : det += p;
488 : }
489 :
490 0 : if (det == 0)
491 0 : return FALSE;
492 :
493 0 : det = 1 / det;
494 0 : for (j = 0; j < 3; j++)
495 : {
496 0 : for (i = 0; i < 3; i++)
497 : {
498 : double p;
499 0 : int ai = a[i];
500 0 : int aj = a[j];
501 0 : int bi = b[i];
502 0 : int bj = b[j];
503 :
504 0 : p = (src->m[ai][aj] * src->m[bi][bj] -
505 0 : src->m[ai][bj] * src->m[bi][aj]);
506 :
507 0 : if (((i + j) & 1) != 0)
508 0 : p = -p;
509 :
510 0 : dst->m[j][i] = det * p;
511 : }
512 : }
513 :
514 0 : return TRUE;
515 : }
516 :
517 : PIXMAN_EXPORT pixman_bool_t
518 0 : 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 0 : for (j = 0; j < 3; j++)
526 : {
527 0 : a = 0;
528 0 : for (i = 0; i < 3; i++)
529 0 : a += t->m[j][i] * v->v[i];
530 0 : result.v[j] = a;
531 : }
532 :
533 0 : if (!result.v[2])
534 0 : return FALSE;
535 :
536 0 : for (j = 0; j < 2; j++)
537 0 : v->v[j] = result.v[j] / result.v[2];
538 :
539 0 : v->v[2] = 1;
540 :
541 0 : return TRUE;
542 : }
543 :
544 : PIXMAN_EXPORT void
545 0 : 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 0 : for (j = 0; j < 3; j++)
553 : {
554 0 : a = 0;
555 0 : for (i = 0; i < 3; i++)
556 0 : a += t->m[j][i] * v->v[i];
557 0 : result.v[j] = a;
558 : }
559 :
560 0 : *v = result;
561 0 : }
562 :
563 : PIXMAN_EXPORT void
564 0 : 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 0 : for (dy = 0; dy < 3; dy++)
573 : {
574 0 : for (dx = 0; dx < 3; dx++)
575 : {
576 0 : double v = 0;
577 0 : for (o = 0; o < 3; o++)
578 0 : v += l->m[dy][o] * r->m[o][dx];
579 0 : d.m[dy][dx] = v;
580 : }
581 : }
582 :
583 0 : *dst = d;
584 0 : }
585 :
586 : PIXMAN_EXPORT void
587 0 : pixman_f_transform_init_scale (struct pixman_f_transform *t,
588 : double sx,
589 : double sy)
590 : {
591 0 : t->m[0][0] = sx;
592 0 : t->m[0][1] = 0;
593 0 : t->m[0][2] = 0;
594 0 : t->m[1][0] = 0;
595 0 : t->m[1][1] = sy;
596 0 : t->m[1][2] = 0;
597 0 : t->m[2][0] = 0;
598 0 : t->m[2][1] = 0;
599 0 : t->m[2][2] = 1;
600 0 : }
601 :
602 : PIXMAN_EXPORT pixman_bool_t
603 0 : 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 0 : if (sx == 0 || sy == 0)
611 0 : return FALSE;
612 :
613 0 : if (forward)
614 : {
615 0 : pixman_f_transform_init_scale (&t, sx, sy);
616 0 : pixman_f_transform_multiply (forward, &t, forward);
617 : }
618 :
619 0 : if (reverse)
620 : {
621 0 : pixman_f_transform_init_scale (&t, 1 / sx, 1 / sy);
622 0 : pixman_f_transform_multiply (reverse, reverse, &t);
623 : }
624 :
625 0 : return TRUE;
626 : }
627 :
628 : PIXMAN_EXPORT void
629 0 : pixman_f_transform_init_rotate (struct pixman_f_transform *t,
630 : double c,
631 : double s)
632 : {
633 0 : t->m[0][0] = c;
634 0 : t->m[0][1] = -s;
635 0 : t->m[0][2] = 0;
636 0 : t->m[1][0] = s;
637 0 : t->m[1][1] = c;
638 0 : t->m[1][2] = 0;
639 0 : t->m[2][0] = 0;
640 0 : t->m[2][1] = 0;
641 0 : t->m[2][2] = 1;
642 0 : }
643 :
644 : PIXMAN_EXPORT pixman_bool_t
645 0 : 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 0 : if (forward)
653 : {
654 0 : pixman_f_transform_init_rotate (&t, c, s);
655 0 : pixman_f_transform_multiply (forward, &t, forward);
656 : }
657 :
658 0 : if (reverse)
659 : {
660 0 : pixman_f_transform_init_rotate (&t, c, -s);
661 0 : pixman_f_transform_multiply (reverse, reverse, &t);
662 : }
663 :
664 0 : return TRUE;
665 : }
666 :
667 : PIXMAN_EXPORT void
668 0 : pixman_f_transform_init_translate (struct pixman_f_transform *t,
669 : double tx,
670 : double ty)
671 : {
672 0 : t->m[0][0] = 1;
673 0 : t->m[0][1] = 0;
674 0 : t->m[0][2] = tx;
675 0 : t->m[1][0] = 0;
676 0 : t->m[1][1] = 1;
677 0 : t->m[1][2] = ty;
678 0 : t->m[2][0] = 0;
679 0 : t->m[2][1] = 0;
680 0 : t->m[2][2] = 1;
681 0 : }
682 :
683 : PIXMAN_EXPORT pixman_bool_t
684 0 : 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 0 : if (forward)
692 : {
693 0 : pixman_f_transform_init_translate (&t, tx, ty);
694 0 : pixman_f_transform_multiply (forward, &t, forward);
695 : }
696 :
697 0 : if (reverse)
698 : {
699 0 : pixman_f_transform_init_translate (&t, -tx, -ty);
700 0 : pixman_f_transform_multiply (reverse, reverse, &t);
701 : }
702 :
703 0 : return TRUE;
704 : }
705 :
706 : PIXMAN_EXPORT pixman_bool_t
707 0 : 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 0 : v[0].v[0] = b->x1;
715 0 : v[0].v[1] = b->y1;
716 0 : v[0].v[2] = 1;
717 0 : v[1].v[0] = b->x2;
718 0 : v[1].v[1] = b->y1;
719 0 : v[1].v[2] = 1;
720 0 : v[2].v[0] = b->x2;
721 0 : v[2].v[1] = b->y2;
722 0 : v[2].v[2] = 1;
723 0 : v[3].v[0] = b->x1;
724 0 : v[3].v[1] = b->y2;
725 0 : v[3].v[2] = 1;
726 :
727 0 : for (i = 0; i < 4; i++)
728 : {
729 0 : if (!pixman_f_transform_point (t, &v[i]))
730 0 : return FALSE;
731 :
732 0 : x1 = floor (v[i].v[0]);
733 0 : y1 = floor (v[i].v[1]);
734 0 : x2 = ceil (v[i].v[0]);
735 0 : y2 = ceil (v[i].v[1]);
736 :
737 0 : if (i == 0)
738 : {
739 0 : b->x1 = x1;
740 0 : b->y1 = y1;
741 0 : b->x2 = x2;
742 0 : b->y2 = y2;
743 : }
744 : else
745 : {
746 0 : if (x1 < b->x1) b->x1 = x1;
747 0 : if (y1 < b->y1) b->y1 = y1;
748 0 : if (x2 > b->x2) b->x2 = x2;
749 0 : if (y2 > b->y2) b->y2 = y2;
750 : }
751 : }
752 :
753 0 : return TRUE;
754 : }
755 :
756 : PIXMAN_EXPORT void
757 0 : pixman_f_transform_init_identity (struct pixman_f_transform *t)
758 : {
759 : int i, j;
760 :
761 0 : for (j = 0; j < 3; j++)
762 : {
763 0 : for (i = 0; i < 3; i++)
764 0 : t->m[j][i] = i == j ? 1 : 0;
765 : }
766 0 : }
|