Coverage Report

Created: 2025-07-23 08:13

/src/cairo/subprojects/pixman-0.44.2/pixman/pixman-matrix.c
Line
Count
Source (jump to first uncovered line)
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 <pixman-config.h>
29
#endif
30
31
#include <math.h>
32
#include <string.h>
33
#include "pixman-private.h"
34
35
0
#define F(x)    pixman_int_to_fixed (x)
36
37
static force_inline int
38
count_leading_zeros (uint32_t x)
39
0
{
40
0
#ifdef HAVE_BUILTIN_CLZ
41
0
    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
0
}
52
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
 */
64
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
0
{
72
0
    uint64_t tmp, remainder, result_lo;
73
0
    assert(div < ((uint64_t)1 << 48));
74
75
0
    remainder = hi % div;
76
0
    *result_hi = hi / div;
77
78
0
    tmp = (remainder << 16) + (lo >> 48);
79
0
    result_lo = tmp / div;
80
0
    remainder = tmp % div;
81
82
0
    tmp = (remainder << 16) + ((lo >> 32) & 0xFFFF);
83
0
    result_lo = (result_lo << 16) + (tmp / div);
84
0
    remainder = tmp % div;
85
86
0
    tmp = (remainder << 16) + ((lo >> 16) & 0xFFFF);
87
0
    result_lo = (result_lo << 16) + (tmp / div);
88
0
    remainder = tmp % div;
89
90
0
    tmp = (remainder << 16) + (lo & 0xFFFF);
91
0
    result_lo = (result_lo << 16) + (tmp / div);
92
0
    remainder = tmp % div;
93
94
    /* round to nearest */
95
0
    if (remainder * 2 >= div && ++result_lo == 0)
96
0
        *result_hi += 1;
97
98
0
    return result_lo;
99
0
}
100
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
0
{
108
0
    uint64_t result_lo, result_hi;
109
0
    int sign = 0;
110
0
    if (div < 0)
111
0
    {
112
0
        div = -div;
113
0
        sign ^= 1;
114
0
    }
115
0
    if (hi < 0)
116
0
    {
117
0
        if (lo != 0)
118
0
            hi++;
119
0
        hi = -hi;
120
0
        lo = -lo;
121
0
        sign ^= 1;
122
0
    }
123
0
    result_lo = rounded_udiv_128_by_48 (hi, lo, div, &result_hi);
124
0
    if (sign)
125
0
    {
126
0
        if (result_lo != 0)
127
0
            result_hi++;
128
0
        result_hi = -result_hi;
129
0
        result_lo = -result_lo;
130
0
    }
131
0
    if (signed_result_hi)
132
0
    {
133
0
        *signed_result_hi = result_hi;
134
0
    }
135
0
    return result_lo;
136
0
}
137
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
0
{
149
    /* separate integer and fractional parts */
150
0
    hi += lo >> 16;
151
0
    lo &= 0xFFFF;
152
153
0
    if (scalebits <= 0)
154
0
    {
155
0
        *rlo = hi >> (-scalebits);
156
0
        *rhi = *rlo >> 63;
157
0
    }
158
0
    else
159
0
    {
160
0
        *rhi = hi >> (64 - scalebits);
161
0
        *rlo = (uint64_t)hi << scalebits;
162
0
        if (scalebits < 16)
163
0
            *rlo += lo >> (16 - scalebits);
164
0
        else
165
0
            *rlo += lo << (scalebits - 16);
166
0
    }
167
0
}
168
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
0
{
176
0
    if ((lo >> 63) != hi)
177
0
    {
178
0
        *clampflag = TRUE;
179
0
        return hi >= 0 ? INT64_MAX : INT64_MIN;
180
0
    }
181
0
    else
182
0
    {
183
0
        return lo;
184
0
    }
185
0
}
186
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
1.37k
{
202
1.37k
    pixman_bool_t clampflag = FALSE;
203
1.37k
    int i;
204
1.37k
    int64_t tmp[3][2], divint;
205
1.37k
    uint16_t divfrac;
206
207
    /* input vector values must have no more than 31 bits (including sign)
208
     * in the integer part */
209
1.37k
    assert (v->v[0] <   ((pixman_fixed_48_16_t)1 << (30 + 16)));
210
1.37k
    assert (v->v[0] >= -((pixman_fixed_48_16_t)1 << (30 + 16)));
211
1.37k
    assert (v->v[1] <   ((pixman_fixed_48_16_t)1 << (30 + 16)));
212
1.37k
    assert (v->v[1] >= -((pixman_fixed_48_16_t)1 << (30 + 16)));
213
1.37k
    assert (v->v[2] <   ((pixman_fixed_48_16_t)1 << (30 + 16)));
214
1.37k
    assert (v->v[2] >= -((pixman_fixed_48_16_t)1 << (30 + 16)));
215
216
5.50k
    for (i = 0; i < 3; i++)
217
4.12k
    {
218
4.12k
        tmp[i][0] = (int64_t)t->matrix[i][0] * (v->v[0] >> 16);
219
4.12k
        tmp[i][1] = (int64_t)t->matrix[i][0] * (v->v[0] & 0xFFFF);
220
4.12k
        tmp[i][0] += (int64_t)t->matrix[i][1] * (v->v[1] >> 16);
221
4.12k
        tmp[i][1] += (int64_t)t->matrix[i][1] * (v->v[1] & 0xFFFF);
222
4.12k
        tmp[i][0] += (int64_t)t->matrix[i][2] * (v->v[2] >> 16);
223
4.12k
        tmp[i][1] += (int64_t)t->matrix[i][2] * (v->v[2] & 0xFFFF);
224
4.12k
    }
225
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
1.37k
    divint  = tmp[2][0] + (tmp[2][1] >> 16);
231
1.37k
    divfrac = tmp[2][1] & 0xFFFF;
232
233
1.37k
    if (divint == pixman_fixed_1 && divfrac == 0)
234
1.37k
    {
235
        /*
236
         * this is a simple affine transformation
237
         */
238
1.37k
        result->v[0] = tmp[0][0] + ((tmp[0][1] + 0x8000) >> 16);
239
1.37k
        result->v[1] = tmp[1][0] + ((tmp[1][1] + 0x8000) >> 16);
240
1.37k
        result->v[2] = pixman_fixed_1;
241
1.37k
    }
242
0
    else if (divint == 0 && divfrac == 0)
243
0
    {
244
        /*
245
         * handle zero divisor (if the values are non-zero, set the
246
         * results to maximum positive or minimum negative)
247
         */
248
0
        clampflag = TRUE;
249
250
0
        result->v[0] = tmp[0][0] + ((tmp[0][1] + 0x8000) >> 16);
251
0
        result->v[1] = tmp[1][0] + ((tmp[1][1] + 0x8000) >> 16);
252
253
0
        if (result->v[0] > 0)
254
0
            result->v[0] = INT64_MAX;
255
0
        else if (result->v[0] < 0)
256
0
            result->v[0] = INT64_MIN;
257
258
0
        if (result->v[1] > 0)
259
0
            result->v[1] = INT64_MAX;
260
0
        else if (result->v[1] < 0)
261
0
            result->v[1] = INT64_MIN;
262
0
    }
263
0
    else
264
0
    {
265
        /*
266
         * projective transformation, analyze the top 32 bits of the divisor
267
         */
268
0
        int32_t hi32divbits = divint >> 32;
269
0
        if (hi32divbits < 0)
270
0
            hi32divbits = ~hi32divbits;
271
272
0
        if (hi32divbits == 0)
273
0
        {
274
            /* the divisor is small, we can actually keep all the bits */
275
0
            int64_t hi, rhi, lo, rlo;
276
0
            int64_t div = ((uint64_t)divint << 16) + divfrac;
277
278
0
            fixed_64_16_to_int128 (tmp[0][0], tmp[0][1], &hi, &lo, 32);
279
0
            rlo = rounded_sdiv_128_by_49 (hi, lo, div, &rhi);
280
0
            result->v[0] = fixed_112_16_to_fixed_48_16 (rhi, rlo, &clampflag);
281
282
0
            fixed_64_16_to_int128 (tmp[1][0], tmp[1][1], &hi, &lo, 32);
283
0
            rlo = rounded_sdiv_128_by_49 (hi, lo, div, &rhi);
284
0
            result->v[1] = fixed_112_16_to_fixed_48_16 (rhi, rlo, &clampflag);
285
0
        }
286
0
        else
287
0
        {
288
            /* the divisor needs to be reduced to 48 bits */
289
0
            int64_t hi, rhi, lo, rlo, div;
290
0
            int shift = 32 - count_leading_zeros (hi32divbits);
291
0
            fixed_64_16_to_int128 (divint, divfrac, &hi, &div, 16 - shift);
292
293
0
            fixed_64_16_to_int128 (tmp[0][0], tmp[0][1], &hi, &lo, 32 - shift);
294
0
            rlo = rounded_sdiv_128_by_49 (hi, lo, div, &rhi);
295
0
            result->v[0] = fixed_112_16_to_fixed_48_16 (rhi, rlo, &clampflag);
296
297
0
            fixed_64_16_to_int128 (tmp[1][0], tmp[1][1], &hi, &lo, 32 - shift);
298
0
            rlo = rounded_sdiv_128_by_49 (hi, lo, div, &rhi);
299
0
            result->v[1] = fixed_112_16_to_fixed_48_16 (rhi, rlo, &clampflag);
300
0
        }
301
0
    }
302
1.37k
    result->v[2] = pixman_fixed_1;
303
1.37k
    return !clampflag;
304
1.37k
}
305
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
0
{
311
0
    int64_t hi0, lo0, hi1, lo1;
312
313
    /* input vector values must have no more than 31 bits (including sign)
314
     * in the integer part */
315
0
    assert (v->v[0] <   ((pixman_fixed_48_16_t)1 << (30 + 16)));
316
0
    assert (v->v[0] >= -((pixman_fixed_48_16_t)1 << (30 + 16)));
317
0
    assert (v->v[1] <   ((pixman_fixed_48_16_t)1 << (30 + 16)));
318
0
    assert (v->v[1] >= -((pixman_fixed_48_16_t)1 << (30 + 16)));
319
320
0
    hi0  = (int64_t)t->matrix[0][0] * (v->v[0] >> 16);
321
0
    lo0  = (int64_t)t->matrix[0][0] * (v->v[0] & 0xFFFF);
322
0
    hi0 += (int64_t)t->matrix[0][1] * (v->v[1] >> 16);
323
0
    lo0 += (int64_t)t->matrix[0][1] * (v->v[1] & 0xFFFF);
324
0
    hi0 += (int64_t)t->matrix[0][2];
325
326
0
    hi1  = (int64_t)t->matrix[1][0] * (v->v[0] >> 16);
327
0
    lo1  = (int64_t)t->matrix[1][0] * (v->v[0] & 0xFFFF);
328
0
    hi1 += (int64_t)t->matrix[1][1] * (v->v[1] >> 16);
329
0
    lo1 += (int64_t)t->matrix[1][1] * (v->v[1] & 0xFFFF);
330
0
    hi1 += (int64_t)t->matrix[1][2];
331
332
0
    result->v[0] = hi0 + ((lo0 + 0x8000) >> 16);
333
0
    result->v[1] = hi1 + ((lo1 + 0x8000) >> 16);
334
0
    result->v[2] = pixman_fixed_1;
335
0
}
336
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
180
{
342
180
    int i;
343
180
    int64_t tmp[3][2];
344
345
    /* input vector values must have no more than 31 bits (including sign)
346
     * in the integer part */
347
180
    assert (v->v[0] <   ((pixman_fixed_48_16_t)1 << (30 + 16)));
348
180
    assert (v->v[0] >= -((pixman_fixed_48_16_t)1 << (30 + 16)));
349
180
    assert (v->v[1] <   ((pixman_fixed_48_16_t)1 << (30 + 16)));
350
180
    assert (v->v[1] >= -((pixman_fixed_48_16_t)1 << (30 + 16)));
351
180
    assert (v->v[2] <   ((pixman_fixed_48_16_t)1 << (30 + 16)));
352
180
    assert (v->v[2] >= -((pixman_fixed_48_16_t)1 << (30 + 16)));
353
354
720
    for (i = 0; i < 3; i++)
355
540
    {
356
540
        tmp[i][0] = (int64_t)t->matrix[i][0] * (v->v[0] >> 16);
357
540
        tmp[i][1] = (int64_t)t->matrix[i][0] * (v->v[0] & 0xFFFF);
358
540
        tmp[i][0] += (int64_t)t->matrix[i][1] * (v->v[1] >> 16);
359
540
        tmp[i][1] += (int64_t)t->matrix[i][1] * (v->v[1] & 0xFFFF);
360
540
        tmp[i][0] += (int64_t)t->matrix[i][2] * (v->v[2] >> 16);
361
540
        tmp[i][1] += (int64_t)t->matrix[i][2] * (v->v[2] & 0xFFFF);
362
540
    }
363
364
180
    result->v[0] = tmp[0][0] + ((tmp[0][1] + 0x8000) >> 16);
365
180
    result->v[1] = tmp[1][0] + ((tmp[1][1] + 0x8000) >> 16);
366
180
    result->v[2] = tmp[2][0] + ((tmp[2][1] + 0x8000) >> 16);
367
180
}
368
369
PIXMAN_EXPORT void
370
pixman_transform_init_identity (struct pixman_transform *matrix)
371
0
{
372
0
    int i;
373
374
0
    memset (matrix, '\0', sizeof (struct pixman_transform));
375
0
    for (i = 0; i < 3; i++)
376
0
  matrix->matrix[i][i] = F (1);
377
0
}
378
379
typedef pixman_fixed_32_32_t pixman_fixed_34_30_t;
380
381
PIXMAN_EXPORT pixman_bool_t
382
pixman_transform_point_3d (const struct pixman_transform *transform,
383
                           struct pixman_vector *         vector)
384
180
{
385
180
    pixman_vector_48_16_t tmp;
386
180
    tmp.v[0] = vector->vector[0];
387
180
    tmp.v[1] = vector->vector[1];
388
180
    tmp.v[2] = vector->vector[2];
389
390
180
    pixman_transform_point_31_16_3d (transform, &tmp, &tmp);
391
392
180
    vector->vector[0] = tmp.v[0];
393
180
    vector->vector[1] = tmp.v[1];
394
180
    vector->vector[2] = tmp.v[2];
395
396
180
    return vector->vector[0] == tmp.v[0] &&
397
180
           vector->vector[1] == tmp.v[1] &&
398
180
           vector->vector[2] == tmp.v[2];
399
180
}
400
401
PIXMAN_EXPORT pixman_bool_t
402
pixman_transform_point (const struct pixman_transform *transform,
403
                        struct pixman_vector *         vector)
404
1.37k
{
405
1.37k
    pixman_vector_48_16_t tmp;
406
1.37k
    tmp.v[0] = vector->vector[0];
407
1.37k
    tmp.v[1] = vector->vector[1];
408
1.37k
    tmp.v[2] = vector->vector[2];
409
410
1.37k
    if (!pixman_transform_point_31_16 (transform, &tmp, &tmp))
411
0
        return FALSE;
412
413
1.37k
    vector->vector[0] = tmp.v[0];
414
1.37k
    vector->vector[1] = tmp.v[1];
415
1.37k
    vector->vector[2] = tmp.v[2];
416
417
1.37k
    return vector->vector[0] == tmp.v[0] &&
418
1.37k
           vector->vector[1] == tmp.v[1] &&
419
1.37k
           vector->vector[2] == tmp.v[2];
420
1.37k
}
421
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
0
{
427
0
    struct pixman_transform d;
428
0
    int dx, dy;
429
0
    int o;
430
431
0
    for (dy = 0; dy < 3; dy++)
432
0
    {
433
0
  for (dx = 0; dx < 3; dx++)
434
0
  {
435
0
      pixman_fixed_48_16_t v;
436
0
      pixman_fixed_32_32_t partial;
437
      
438
0
      v = 0;
439
0
      for (o = 0; o < 3; o++)
440
0
      {
441
0
    partial =
442
0
        (pixman_fixed_32_32_t) l->matrix[dy][o] *
443
0
        (pixman_fixed_32_32_t) r->matrix[o][dx];
444
445
0
    v += (partial + 0x8000) >> 16;
446
0
      }
447
448
0
      if (v > pixman_max_fixed_48_16 || v < pixman_min_fixed_48_16)
449
0
    return FALSE;
450
      
451
0
      d.matrix[dy][dx] = (pixman_fixed_t) v;
452
0
  }
453
0
    }
454
455
0
    *dst = d;
456
0
    return TRUE;
457
0
}
458
459
PIXMAN_EXPORT void
460
pixman_transform_init_scale (struct pixman_transform *t,
461
                             pixman_fixed_t           sx,
462
                             pixman_fixed_t           sy)
463
0
{
464
0
    memset (t, '\0', sizeof (struct pixman_transform));
465
466
0
    t->matrix[0][0] = sx;
467
0
    t->matrix[1][1] = sy;
468
0
    t->matrix[2][2] = F (1);
469
0
}
470
471
static pixman_fixed_t
472
fixed_inverse (pixman_fixed_t x)
473
0
{
474
0
    return (pixman_fixed_t) ((((pixman_fixed_48_16_t) F (1)) * F (1)) / x);
475
0
}
476
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
0
{
483
0
    struct pixman_transform t;
484
485
0
    if (sx == 0 || sy == 0)
486
0
  return FALSE;
487
488
0
    if (forward)
489
0
    {
490
0
  pixman_transform_init_scale (&t, sx, sy);
491
0
  if (!pixman_transform_multiply (forward, &t, forward))
492
0
      return FALSE;
493
0
    }
494
    
495
0
    if (reverse)
496
0
    {
497
0
  pixman_transform_init_scale (&t, fixed_inverse (sx),
498
0
                               fixed_inverse (sy));
499
0
  if (!pixman_transform_multiply (reverse, reverse, &t))
500
0
      return FALSE;
501
0
    }
502
    
503
0
    return TRUE;
504
0
}
505
506
PIXMAN_EXPORT void
507
pixman_transform_init_rotate (struct pixman_transform *t,
508
                              pixman_fixed_t           c,
509
                              pixman_fixed_t           s)
510
0
{
511
0
    memset (t, '\0', sizeof (struct pixman_transform));
512
513
0
    t->matrix[0][0] = c;
514
0
    t->matrix[0][1] = -s;
515
0
    t->matrix[1][0] = s;
516
0
    t->matrix[1][1] = c;
517
0
    t->matrix[2][2] = F (1);
518
0
}
519
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
0
{
526
0
    struct pixman_transform t;
527
528
0
    if (forward)
529
0
    {
530
0
  pixman_transform_init_rotate (&t, c, s);
531
0
  if (!pixman_transform_multiply (forward, &t, forward))
532
0
      return FALSE;
533
0
    }
534
535
0
    if (reverse)
536
0
    {
537
0
  pixman_transform_init_rotate (&t, c, -s);
538
0
  if (!pixman_transform_multiply (reverse, reverse, &t))
539
0
      return FALSE;
540
0
    }
541
    
542
0
    return TRUE;
543
0
}
544
545
PIXMAN_EXPORT void
546
pixman_transform_init_translate (struct pixman_transform *t,
547
                                 pixman_fixed_t           tx,
548
                                 pixman_fixed_t           ty)
549
0
{
550
0
    memset (t, '\0', sizeof (struct pixman_transform));
551
552
0
    t->matrix[0][0] = F (1);
553
0
    t->matrix[0][2] = tx;
554
0
    t->matrix[1][1] = F (1);
555
0
    t->matrix[1][2] = ty;
556
0
    t->matrix[2][2] = F (1);
557
0
}
558
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
0
{
565
0
    struct pixman_transform t;
566
567
0
    if (forward)
568
0
    {
569
0
  pixman_transform_init_translate (&t, tx, ty);
570
571
0
  if (!pixman_transform_multiply (forward, &t, forward))
572
0
      return FALSE;
573
0
    }
574
575
0
    if (reverse)
576
0
    {
577
0
  pixman_transform_init_translate (&t, -tx, -ty);
578
579
0
  if (!pixman_transform_multiply (reverse, reverse, &t))
580
0
      return FALSE;
581
0
    }
582
0
    return TRUE;
583
0
}
584
585
PIXMAN_EXPORT pixman_bool_t
586
pixman_transform_bounds (const struct pixman_transform *matrix,
587
                         struct pixman_box16 *          b)
588
589
0
{
590
0
    struct pixman_vector v[4];
591
0
    int i;
592
0
    int x1, y1, x2, y2;
593
594
0
    v[0].vector[0] = F (b->x1);
595
0
    v[0].vector[1] = F (b->y1);
596
0
    v[0].vector[2] = F (1);
597
598
0
    v[1].vector[0] = F (b->x2);
599
0
    v[1].vector[1] = F (b->y1);
600
0
    v[1].vector[2] = F (1);
601
602
0
    v[2].vector[0] = F (b->x2);
603
0
    v[2].vector[1] = F (b->y2);
604
0
    v[2].vector[2] = F (1);
605
606
0
    v[3].vector[0] = F (b->x1);
607
0
    v[3].vector[1] = F (b->y2);
608
0
    v[3].vector[2] = F (1);
609
610
0
    for (i = 0; i < 4; i++)
611
0
    {
612
0
  if (!pixman_transform_point (matrix, &v[i]))
613
0
      return FALSE;
614
615
0
  x1 = pixman_fixed_to_int (v[i].vector[0]);
616
0
  y1 = pixman_fixed_to_int (v[i].vector[1]);
617
0
  x2 = pixman_fixed_to_int (pixman_fixed_ceil (v[i].vector[0]));
618
0
  y2 = pixman_fixed_to_int (pixman_fixed_ceil (v[i].vector[1]));
619
620
0
  if (i == 0)
621
0
  {
622
0
      b->x1 = x1;
623
0
      b->y1 = y1;
624
0
      b->x2 = x2;
625
0
      b->y2 = y2;
626
0
  }
627
0
  else
628
0
  {
629
0
      if (x1 < b->x1) b->x1 = x1;
630
0
      if (y1 < b->y1) b->y1 = y1;
631
0
      if (x2 > b->x2) b->x2 = x2;
632
0
      if (y2 > b->y2) b->y2 = y2;
633
0
  }
634
0
    }
635
636
0
    return TRUE;
637
0
}
638
639
PIXMAN_EXPORT pixman_bool_t
640
pixman_transform_invert (struct pixman_transform *      dst,
641
                         const struct pixman_transform *src)
642
0
{
643
0
    struct pixman_f_transform m;
644
645
0
    pixman_f_transform_from_pixman_transform (&m, src);
646
647
0
    if (!pixman_f_transform_invert (&m, &m))
648
0
  return FALSE;
649
650
0
    if (!pixman_transform_from_pixman_f_transform (dst, &m))
651
0
  return FALSE;
652
653
0
    return TRUE;
654
0
}
655
656
static pixman_bool_t
657
within_epsilon (pixman_fixed_t a,
658
                pixman_fixed_t b,
659
                pixman_fixed_t epsilon)
660
0
{
661
0
    pixman_fixed_t t = a - b;
662
663
0
    if (t < 0)
664
0
  t = -t;
665
666
0
    return t <= epsilon;
667
0
}
668
669
0
#define EPSILON (pixman_fixed_t) (2)
670
671
0
#define IS_SAME(a, b) (within_epsilon (a, b, EPSILON))
672
0
#define IS_ZERO(a)    (within_epsilon (a, 0, EPSILON))
673
0
#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
0
#define IS_INT(a)    (IS_ZERO (pixman_fixed_frac (a)))
679
680
PIXMAN_EXPORT pixman_bool_t
681
pixman_transform_is_identity (const struct pixman_transform *t)
682
0
{
683
0
    return (IS_SAME (t->matrix[0][0], t->matrix[1][1]) &&
684
0
      IS_SAME (t->matrix[0][0], t->matrix[2][2]) &&
685
0
      !IS_ZERO (t->matrix[0][0]) &&
686
0
      IS_ZERO (t->matrix[0][1]) &&
687
0
      IS_ZERO (t->matrix[0][2]) &&
688
0
      IS_ZERO (t->matrix[1][0]) &&
689
0
      IS_ZERO (t->matrix[1][2]) &&
690
0
      IS_ZERO (t->matrix[2][0]) &&
691
0
      IS_ZERO (t->matrix[2][1]));
692
0
}
693
694
PIXMAN_EXPORT pixman_bool_t
695
pixman_transform_is_scale (const struct pixman_transform *t)
696
0
{
697
0
    return (!IS_ZERO (t->matrix[0][0]) &&
698
0
            IS_ZERO (t->matrix[0][1]) &&
699
0
            IS_ZERO (t->matrix[0][2]) &&
700
701
0
            IS_ZERO (t->matrix[1][0]) &&
702
0
            !IS_ZERO (t->matrix[1][1]) &&
703
0
            IS_ZERO (t->matrix[1][2]) &&
704
705
0
            IS_ZERO (t->matrix[2][0]) &&
706
0
            IS_ZERO (t->matrix[2][1]) &&
707
0
            !IS_ZERO (t->matrix[2][2]));
708
0
}
709
710
PIXMAN_EXPORT pixman_bool_t
711
pixman_transform_is_int_translate (const struct pixman_transform *t)
712
0
{
713
0
    return (IS_ONE (t->matrix[0][0]) &&
714
0
            IS_ZERO (t->matrix[0][1]) &&
715
0
            IS_INT (t->matrix[0][2]) &&
716
717
0
            IS_ZERO (t->matrix[1][0]) &&
718
0
            IS_ONE (t->matrix[1][1]) &&
719
0
            IS_INT (t->matrix[1][2]) &&
720
721
0
            IS_ZERO (t->matrix[2][0]) &&
722
0
            IS_ZERO (t->matrix[2][1]) &&
723
0
            IS_ONE (t->matrix[2][2]));
724
0
}
725
726
PIXMAN_EXPORT pixman_bool_t
727
pixman_transform_is_inverse (const struct pixman_transform *a,
728
                             const struct pixman_transform *b)
729
0
{
730
0
    struct pixman_transform t;
731
732
0
    if (!pixman_transform_multiply (&t, a, b))
733
0
  return FALSE;
734
735
0
    return pixman_transform_is_identity (&t);
736
0
}
737
738
PIXMAN_EXPORT void
739
pixman_f_transform_from_pixman_transform (struct pixman_f_transform *    ft,
740
                                          const struct pixman_transform *t)
741
0
{
742
0
    int i, j;
743
744
0
    for (j = 0; j < 3; j++)
745
0
    {
746
0
  for (i = 0; i < 3; i++)
747
0
      ft->m[j][i] = pixman_fixed_to_double (t->matrix[j][i]);
748
0
    }
749
0
}
750
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
0
{
755
0
    int i, j;
756
757
0
    for (j = 0; j < 3; j++)
758
0
    {
759
0
  for (i = 0; i < 3; i++)
760
0
  {
761
0
      double d = ft->m[j][i];
762
0
      if (d < -32767.0 || d > 32767.0)
763
0
    return FALSE;
764
0
      d = d * 65536.0 + 0.5;
765
0
      t->matrix[j][i] = (pixman_fixed_t) floor (d);
766
0
  }
767
0
    }
768
    
769
0
    return TRUE;
770
0
}
771
772
PIXMAN_EXPORT pixman_bool_t
773
pixman_f_transform_invert (struct pixman_f_transform *      dst,
774
                           const struct pixman_f_transform *src)
775
0
{
776
0
    static const int a[3] = { 2, 2, 1 };
777
0
    static const int b[3] = { 1, 0, 0 };
778
0
    pixman_f_transform_t d;
779
0
    double det;
780
0
    int i, j;
781
782
0
    det = 0;
783
0
    for (i = 0; i < 3; i++)
784
0
    {
785
0
  double p;
786
0
  int ai = a[i];
787
0
  int bi = b[i];
788
0
  p = src->m[i][0] * (src->m[ai][2] * src->m[bi][1] -
789
0
                      src->m[ai][1] * src->m[bi][2]);
790
0
  if (i == 1)
791
0
      p = -p;
792
0
  det += p;
793
0
    }
794
    
795
0
    if (det == 0)
796
0
  return FALSE;
797
    
798
0
    det = 1 / det;
799
0
    for (j = 0; j < 3; j++)
800
0
    {
801
0
  for (i = 0; i < 3; i++)
802
0
  {
803
0
      double p;
804
0
      int ai = a[i];
805
0
      int aj = a[j];
806
0
      int bi = b[i];
807
0
      int bj = b[j];
808
809
0
      p = (src->m[ai][aj] * src->m[bi][bj] -
810
0
           src->m[ai][bj] * src->m[bi][aj]);
811
      
812
0
      if (((i + j) & 1) != 0)
813
0
    p = -p;
814
      
815
0
      d.m[j][i] = det * p;
816
0
  }
817
0
    }
818
819
0
    *dst = d;
820
821
0
    return TRUE;
822
0
}
823
824
PIXMAN_EXPORT pixman_bool_t
825
pixman_f_transform_point (const struct pixman_f_transform *t,
826
                          struct pixman_f_vector *         v)
827
0
{
828
0
    struct pixman_f_vector result;
829
0
    int i, j;
830
0
    double a;
831
832
0
    for (j = 0; j < 3; j++)
833
0
    {
834
0
  a = 0;
835
0
  for (i = 0; i < 3; i++)
836
0
      a += t->m[j][i] * v->v[i];
837
0
  result.v[j] = a;
838
0
    }
839
    
840
0
    if (!result.v[2])
841
0
  return FALSE;
842
843
0
    for (j = 0; j < 2; j++)
844
0
  v->v[j] = result.v[j] / result.v[2];
845
846
0
    v->v[2] = 1;
847
848
0
    return TRUE;
849
0
}
850
851
PIXMAN_EXPORT void
852
pixman_f_transform_point_3d (const struct pixman_f_transform *t,
853
                             struct pixman_f_vector *         v)
854
0
{
855
0
    struct pixman_f_vector result;
856
0
    int i, j;
857
0
    double a;
858
859
0
    for (j = 0; j < 3; j++)
860
0
    {
861
0
  a = 0;
862
0
  for (i = 0; i < 3; i++)
863
0
      a += t->m[j][i] * v->v[i];
864
0
  result.v[j] = a;
865
0
    }
866
    
867
0
    *v = result;
868
0
}
869
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
0
{
875
0
    struct pixman_f_transform d;
876
0
    int dx, dy;
877
0
    int o;
878
879
0
    for (dy = 0; dy < 3; dy++)
880
0
    {
881
0
  for (dx = 0; dx < 3; dx++)
882
0
  {
883
0
      double v = 0;
884
0
      for (o = 0; o < 3; o++)
885
0
    v += l->m[dy][o] * r->m[o][dx];
886
0
      d.m[dy][dx] = v;
887
0
  }
888
0
    }
889
    
890
0
    *dst = d;
891
0
}
892
893
PIXMAN_EXPORT void
894
pixman_f_transform_init_scale (struct pixman_f_transform *t,
895
                               double                     sx,
896
                               double                     sy)
897
0
{
898
0
    t->m[0][0] = sx;
899
0
    t->m[0][1] = 0;
900
0
    t->m[0][2] = 0;
901
0
    t->m[1][0] = 0;
902
0
    t->m[1][1] = sy;
903
0
    t->m[1][2] = 0;
904
0
    t->m[2][0] = 0;
905
0
    t->m[2][1] = 0;
906
0
    t->m[2][2] = 1;
907
0
}
908
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
0
{
915
0
    struct pixman_f_transform t;
916
917
0
    if (sx == 0 || sy == 0)
918
0
  return FALSE;
919
920
0
    if (forward)
921
0
    {
922
0
  pixman_f_transform_init_scale (&t, sx, sy);
923
0
  pixman_f_transform_multiply (forward, &t, forward);
924
0
    }
925
    
926
0
    if (reverse)
927
0
    {
928
0
  pixman_f_transform_init_scale (&t, 1 / sx, 1 / sy);
929
0
  pixman_f_transform_multiply (reverse, reverse, &t);
930
0
    }
931
    
932
0
    return TRUE;
933
0
}
934
935
PIXMAN_EXPORT void
936
pixman_f_transform_init_rotate (struct pixman_f_transform *t,
937
                                double                     c,
938
                                double                     s)
939
0
{
940
0
    t->m[0][0] = c;
941
0
    t->m[0][1] = -s;
942
0
    t->m[0][2] = 0;
943
0
    t->m[1][0] = s;
944
0
    t->m[1][1] = c;
945
0
    t->m[1][2] = 0;
946
0
    t->m[2][0] = 0;
947
0
    t->m[2][1] = 0;
948
0
    t->m[2][2] = 1;
949
0
}
950
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
0
{
957
0
    struct pixman_f_transform t;
958
959
0
    if (forward)
960
0
    {
961
0
  pixman_f_transform_init_rotate (&t, c, s);
962
0
  pixman_f_transform_multiply (forward, &t, forward);
963
0
    }
964
    
965
0
    if (reverse)
966
0
    {
967
0
  pixman_f_transform_init_rotate (&t, c, -s);
968
0
  pixman_f_transform_multiply (reverse, reverse, &t);
969
0
    }
970
971
0
    return TRUE;
972
0
}
973
974
PIXMAN_EXPORT void
975
pixman_f_transform_init_translate (struct pixman_f_transform *t,
976
                                   double                     tx,
977
                                   double                     ty)
978
0
{
979
0
    t->m[0][0] = 1;
980
0
    t->m[0][1] = 0;
981
0
    t->m[0][2] = tx;
982
0
    t->m[1][0] = 0;
983
0
    t->m[1][1] = 1;
984
0
    t->m[1][2] = ty;
985
0
    t->m[2][0] = 0;
986
0
    t->m[2][1] = 0;
987
0
    t->m[2][2] = 1;
988
0
}
989
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
0
{
996
0
    struct pixman_f_transform t;
997
998
0
    if (forward)
999
0
    {
1000
0
  pixman_f_transform_init_translate (&t, tx, ty);
1001
0
  pixman_f_transform_multiply (forward, &t, forward);
1002
0
    }
1003
1004
0
    if (reverse)
1005
0
    {
1006
0
  pixman_f_transform_init_translate (&t, -tx, -ty);
1007
0
  pixman_f_transform_multiply (reverse, reverse, &t);
1008
0
    }
1009
1010
0
    return TRUE;
1011
0
}
1012
1013
PIXMAN_EXPORT pixman_bool_t
1014
pixman_f_transform_bounds (const struct pixman_f_transform *t,
1015
                           struct pixman_box16 *            b)
1016
0
{
1017
0
    struct pixman_f_vector v[4];
1018
0
    int i;
1019
0
    int x1, y1, x2, y2;
1020
1021
0
    v[0].v[0] = b->x1;
1022
0
    v[0].v[1] = b->y1;
1023
0
    v[0].v[2] = 1;
1024
0
    v[1].v[0] = b->x2;
1025
0
    v[1].v[1] = b->y1;
1026
0
    v[1].v[2] = 1;
1027
0
    v[2].v[0] = b->x2;
1028
0
    v[2].v[1] = b->y2;
1029
0
    v[2].v[2] = 1;
1030
0
    v[3].v[0] = b->x1;
1031
0
    v[3].v[1] = b->y2;
1032
0
    v[3].v[2] = 1;
1033
1034
0
    for (i = 0; i < 4; i++)
1035
0
    {
1036
0
  if (!pixman_f_transform_point (t, &v[i]))
1037
0
      return FALSE;
1038
1039
0
  x1 = floor (v[i].v[0]);
1040
0
  y1 = floor (v[i].v[1]);
1041
0
  x2 = ceil (v[i].v[0]);
1042
0
  y2 = ceil (v[i].v[1]);
1043
1044
0
  if (i == 0)
1045
0
  {
1046
0
      b->x1 = x1;
1047
0
      b->y1 = y1;
1048
0
      b->x2 = x2;
1049
0
      b->y2 = y2;
1050
0
  }
1051
0
  else
1052
0
  {
1053
0
      if (x1 < b->x1) b->x1 = x1;
1054
0
      if (y1 < b->y1) b->y1 = y1;
1055
0
      if (x2 > b->x2) b->x2 = x2;
1056
0
      if (y2 > b->y2) b->y2 = y2;
1057
0
  }
1058
0
    }
1059
1060
0
    return TRUE;
1061
0
}
1062
1063
PIXMAN_EXPORT void
1064
pixman_f_transform_init_identity (struct pixman_f_transform *t)
1065
0
{
1066
0
    int i, j;
1067
1068
0
    for (j = 0; j < 3; j++)
1069
0
    {
1070
0
  for (i = 0; i < 3; i++)
1071
0
      t->m[j][i] = i == j ? 1 : 0;
1072
0
    }
1073
0
}