/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 | } |