|
1 /* |
|
2 * Copyright © 2002 Keith Packard, member of The XFree86 Project, Inc. |
|
3 * Copyright © 2004 Keith Packard |
|
4 * |
|
5 * Permission to use, copy, modify, distribute, and sell this software and its |
|
6 * documentation for any purpose is hereby granted without fee, provided that |
|
7 * the above copyright notice appear in all copies and that both that |
|
8 * copyright notice and this permission notice appear in supporting |
|
9 * documentation, and that the name of Keith Packard not be used in |
|
10 * advertising or publicity pertaining to distribution of the software without |
|
11 * specific, written prior permission. Keith Packard makes no |
|
12 * representations about the suitability of this software for any purpose. It |
|
13 * is provided "as is" without express or implied warranty. |
|
14 * |
|
15 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, |
|
16 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO |
|
17 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR |
|
18 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, |
|
19 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER |
|
20 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR |
|
21 * PERFORMANCE OF THIS SOFTWARE. |
|
22 */ |
|
23 |
|
24 #ifdef HAVE_CONFIG_H |
|
25 #include <config.h> |
|
26 #endif |
|
27 |
|
28 #include <stdio.h> |
|
29 #include <stdlib.h> |
|
30 #include "pixman-private.h" |
|
31 |
|
32 /* |
|
33 * Compute the smallest value greater than or equal to y which is on a |
|
34 * grid row. |
|
35 */ |
|
36 |
|
37 PIXMAN_EXPORT pixman_fixed_t |
|
38 pixman_sample_ceil_y (pixman_fixed_t y, int n) |
|
39 { |
|
40 pixman_fixed_t f = pixman_fixed_frac (y); |
|
41 pixman_fixed_t i = pixman_fixed_floor (y); |
|
42 |
|
43 f = DIV (f - Y_FRAC_FIRST (n) + (STEP_Y_SMALL (n) - pixman_fixed_e), STEP_Y_SMALL (n)) * STEP_Y_SMALL (n) + |
|
44 Y_FRAC_FIRST (n); |
|
45 |
|
46 if (f > Y_FRAC_LAST (n)) |
|
47 { |
|
48 if (pixman_fixed_to_int (i) == 0x7fff) |
|
49 { |
|
50 f = 0xffff; /* saturate */ |
|
51 } |
|
52 else |
|
53 { |
|
54 f = Y_FRAC_FIRST (n); |
|
55 i += pixman_fixed_1; |
|
56 } |
|
57 } |
|
58 return (i | f); |
|
59 } |
|
60 |
|
61 /* |
|
62 * Compute the largest value strictly less than y which is on a |
|
63 * grid row. |
|
64 */ |
|
65 PIXMAN_EXPORT pixman_fixed_t |
|
66 pixman_sample_floor_y (pixman_fixed_t y, |
|
67 int n) |
|
68 { |
|
69 pixman_fixed_t f = pixman_fixed_frac (y); |
|
70 pixman_fixed_t i = pixman_fixed_floor (y); |
|
71 |
|
72 f = DIV (f - pixman_fixed_e - Y_FRAC_FIRST (n), STEP_Y_SMALL (n)) * STEP_Y_SMALL (n) + |
|
73 Y_FRAC_FIRST (n); |
|
74 |
|
75 if (f < Y_FRAC_FIRST (n)) |
|
76 { |
|
77 if (pixman_fixed_to_int (i) == 0x8000) |
|
78 { |
|
79 f = 0; /* saturate */ |
|
80 } |
|
81 else |
|
82 { |
|
83 f = Y_FRAC_LAST (n); |
|
84 i -= pixman_fixed_1; |
|
85 } |
|
86 } |
|
87 return (i | f); |
|
88 } |
|
89 |
|
90 /* |
|
91 * Step an edge by any amount (including negative values) |
|
92 */ |
|
93 PIXMAN_EXPORT void |
|
94 pixman_edge_step (pixman_edge_t *e, |
|
95 int n) |
|
96 { |
|
97 pixman_fixed_48_16_t ne; |
|
98 |
|
99 e->x += n * e->stepx; |
|
100 |
|
101 ne = e->e + n * (pixman_fixed_48_16_t) e->dx; |
|
102 |
|
103 if (n >= 0) |
|
104 { |
|
105 if (ne > 0) |
|
106 { |
|
107 int nx = (ne + e->dy - 1) / e->dy; |
|
108 e->e = ne - nx * (pixman_fixed_48_16_t) e->dy; |
|
109 e->x += nx * e->signdx; |
|
110 } |
|
111 } |
|
112 else |
|
113 { |
|
114 if (ne <= -e->dy) |
|
115 { |
|
116 int nx = (-ne) / e->dy; |
|
117 e->e = ne + nx * (pixman_fixed_48_16_t) e->dy; |
|
118 e->x -= nx * e->signdx; |
|
119 } |
|
120 } |
|
121 } |
|
122 |
|
123 /* |
|
124 * A private routine to initialize the multi-step |
|
125 * elements of an edge structure |
|
126 */ |
|
127 static void |
|
128 _pixman_edge_multi_init (pixman_edge_t * e, |
|
129 int n, |
|
130 pixman_fixed_t *stepx_p, |
|
131 pixman_fixed_t *dx_p) |
|
132 { |
|
133 pixman_fixed_t stepx; |
|
134 pixman_fixed_48_16_t ne; |
|
135 |
|
136 ne = n * (pixman_fixed_48_16_t) e->dx; |
|
137 stepx = n * e->stepx; |
|
138 |
|
139 if (ne > 0) |
|
140 { |
|
141 int nx = ne / e->dy; |
|
142 ne -= nx * (pixman_fixed_48_16_t)e->dy; |
|
143 stepx += nx * e->signdx; |
|
144 } |
|
145 |
|
146 *dx_p = ne; |
|
147 *stepx_p = stepx; |
|
148 } |
|
149 |
|
150 /* |
|
151 * Initialize one edge structure given the line endpoints and a |
|
152 * starting y value |
|
153 */ |
|
154 PIXMAN_EXPORT void |
|
155 pixman_edge_init (pixman_edge_t *e, |
|
156 int n, |
|
157 pixman_fixed_t y_start, |
|
158 pixman_fixed_t x_top, |
|
159 pixman_fixed_t y_top, |
|
160 pixman_fixed_t x_bot, |
|
161 pixman_fixed_t y_bot) |
|
162 { |
|
163 pixman_fixed_t dx, dy; |
|
164 |
|
165 e->x = x_top; |
|
166 e->e = 0; |
|
167 dx = x_bot - x_top; |
|
168 dy = y_bot - y_top; |
|
169 e->dy = dy; |
|
170 e->dx = 0; |
|
171 |
|
172 if (dy) |
|
173 { |
|
174 if (dx >= 0) |
|
175 { |
|
176 e->signdx = 1; |
|
177 e->stepx = dx / dy; |
|
178 e->dx = dx % dy; |
|
179 e->e = -dy; |
|
180 } |
|
181 else |
|
182 { |
|
183 e->signdx = -1; |
|
184 e->stepx = -(-dx / dy); |
|
185 e->dx = -dx % dy; |
|
186 e->e = 0; |
|
187 } |
|
188 |
|
189 _pixman_edge_multi_init (e, STEP_Y_SMALL (n), |
|
190 &e->stepx_small, &e->dx_small); |
|
191 |
|
192 _pixman_edge_multi_init (e, STEP_Y_BIG (n), |
|
193 &e->stepx_big, &e->dx_big); |
|
194 } |
|
195 pixman_edge_step (e, y_start - y_top); |
|
196 } |
|
197 |
|
198 /* |
|
199 * Initialize one edge structure given a line, starting y value |
|
200 * and a pixel offset for the line |
|
201 */ |
|
202 PIXMAN_EXPORT void |
|
203 pixman_line_fixed_edge_init (pixman_edge_t * e, |
|
204 int n, |
|
205 pixman_fixed_t y, |
|
206 const pixman_line_fixed_t *line, |
|
207 int x_off, |
|
208 int y_off) |
|
209 { |
|
210 pixman_fixed_t x_off_fixed = pixman_int_to_fixed (x_off); |
|
211 pixman_fixed_t y_off_fixed = pixman_int_to_fixed (y_off); |
|
212 const pixman_point_fixed_t *top, *bot; |
|
213 |
|
214 if (line->p1.y <= line->p2.y) |
|
215 { |
|
216 top = &line->p1; |
|
217 bot = &line->p2; |
|
218 } |
|
219 else |
|
220 { |
|
221 top = &line->p2; |
|
222 bot = &line->p1; |
|
223 } |
|
224 |
|
225 pixman_edge_init (e, n, y, |
|
226 top->x + x_off_fixed, |
|
227 top->y + y_off_fixed, |
|
228 bot->x + x_off_fixed, |
|
229 bot->y + y_off_fixed); |
|
230 } |
|
231 |
|
232 PIXMAN_EXPORT void |
|
233 pixman_add_traps (pixman_image_t * image, |
|
234 int16_t x_off, |
|
235 int16_t y_off, |
|
236 int ntrap, |
|
237 const pixman_trap_t *traps) |
|
238 { |
|
239 int bpp; |
|
240 int height; |
|
241 |
|
242 pixman_fixed_t x_off_fixed; |
|
243 pixman_fixed_t y_off_fixed; |
|
244 pixman_edge_t l, r; |
|
245 pixman_fixed_t t, b; |
|
246 |
|
247 _pixman_image_validate (image); |
|
248 |
|
249 height = image->bits.height; |
|
250 bpp = PIXMAN_FORMAT_BPP (image->bits.format); |
|
251 |
|
252 x_off_fixed = pixman_int_to_fixed (x_off); |
|
253 y_off_fixed = pixman_int_to_fixed (y_off); |
|
254 |
|
255 while (ntrap--) |
|
256 { |
|
257 t = traps->top.y + y_off_fixed; |
|
258 if (t < 0) |
|
259 t = 0; |
|
260 t = pixman_sample_ceil_y (t, bpp); |
|
261 |
|
262 b = traps->bot.y + y_off_fixed; |
|
263 if (pixman_fixed_to_int (b) >= height) |
|
264 b = pixman_int_to_fixed (height) - 1; |
|
265 b = pixman_sample_floor_y (b, bpp); |
|
266 |
|
267 if (b >= t) |
|
268 { |
|
269 /* initialize edge walkers */ |
|
270 pixman_edge_init (&l, bpp, t, |
|
271 traps->top.l + x_off_fixed, |
|
272 traps->top.y + y_off_fixed, |
|
273 traps->bot.l + x_off_fixed, |
|
274 traps->bot.y + y_off_fixed); |
|
275 |
|
276 pixman_edge_init (&r, bpp, t, |
|
277 traps->top.r + x_off_fixed, |
|
278 traps->top.y + y_off_fixed, |
|
279 traps->bot.r + x_off_fixed, |
|
280 traps->bot.y + y_off_fixed); |
|
281 |
|
282 pixman_rasterize_edges (image, &l, &r, t, b); |
|
283 } |
|
284 |
|
285 traps++; |
|
286 } |
|
287 } |
|
288 |
|
289 #if 0 |
|
290 static void |
|
291 dump_image (pixman_image_t *image, |
|
292 const char * title) |
|
293 { |
|
294 int i, j; |
|
295 |
|
296 if (!image->type == BITS) |
|
297 printf ("%s is not a regular image\n", title); |
|
298 |
|
299 if (!image->bits.format == PIXMAN_a8) |
|
300 printf ("%s is not an alpha mask\n", title); |
|
301 |
|
302 printf ("\n\n\n%s: \n", title); |
|
303 |
|
304 for (i = 0; i < image->bits.height; ++i) |
|
305 { |
|
306 uint8_t *line = |
|
307 (uint8_t *)&(image->bits.bits[i * image->bits.rowstride]); |
|
308 |
|
309 for (j = 0; j < image->bits.width; ++j) |
|
310 printf ("%c", line[j] ? '#' : ' '); |
|
311 |
|
312 printf ("\n"); |
|
313 } |
|
314 } |
|
315 #endif |
|
316 |
|
317 PIXMAN_EXPORT void |
|
318 pixman_add_trapezoids (pixman_image_t * image, |
|
319 int16_t x_off, |
|
320 int y_off, |
|
321 int ntraps, |
|
322 const pixman_trapezoid_t *traps) |
|
323 { |
|
324 int i; |
|
325 |
|
326 #if 0 |
|
327 dump_image (image, "before"); |
|
328 #endif |
|
329 |
|
330 for (i = 0; i < ntraps; ++i) |
|
331 { |
|
332 const pixman_trapezoid_t *trap = &(traps[i]); |
|
333 |
|
334 if (!pixman_trapezoid_valid (trap)) |
|
335 continue; |
|
336 |
|
337 pixman_rasterize_trapezoid (image, trap, x_off, y_off); |
|
338 } |
|
339 |
|
340 #if 0 |
|
341 dump_image (image, "after"); |
|
342 #endif |
|
343 } |
|
344 |
|
345 PIXMAN_EXPORT void |
|
346 pixman_rasterize_trapezoid (pixman_image_t * image, |
|
347 const pixman_trapezoid_t *trap, |
|
348 int x_off, |
|
349 int y_off) |
|
350 { |
|
351 int bpp; |
|
352 int height; |
|
353 |
|
354 pixman_fixed_t y_off_fixed; |
|
355 pixman_edge_t l, r; |
|
356 pixman_fixed_t t, b; |
|
357 |
|
358 return_if_fail (image->type == BITS); |
|
359 |
|
360 _pixman_image_validate (image); |
|
361 |
|
362 if (!pixman_trapezoid_valid (trap)) |
|
363 return; |
|
364 |
|
365 height = image->bits.height; |
|
366 bpp = PIXMAN_FORMAT_BPP (image->bits.format); |
|
367 |
|
368 y_off_fixed = pixman_int_to_fixed (y_off); |
|
369 |
|
370 t = trap->top + y_off_fixed; |
|
371 if (t < 0) |
|
372 t = 0; |
|
373 t = pixman_sample_ceil_y (t, bpp); |
|
374 |
|
375 b = trap->bottom + y_off_fixed; |
|
376 if (pixman_fixed_to_int (b) >= height) |
|
377 b = pixman_int_to_fixed (height) - 1; |
|
378 b = pixman_sample_floor_y (b, bpp); |
|
379 |
|
380 if (b >= t) |
|
381 { |
|
382 /* initialize edge walkers */ |
|
383 pixman_line_fixed_edge_init (&l, bpp, t, &trap->left, x_off, y_off); |
|
384 pixman_line_fixed_edge_init (&r, bpp, t, &trap->right, x_off, y_off); |
|
385 |
|
386 pixman_rasterize_edges (image, &l, &r, t, b); |
|
387 } |
|
388 } |
|
389 |
|
390 static const pixman_bool_t zero_src_has_no_effect[PIXMAN_N_OPERATORS] = |
|
391 { |
|
392 FALSE, /* Clear 0 0 */ |
|
393 FALSE, /* Src 1 0 */ |
|
394 TRUE, /* Dst 0 1 */ |
|
395 TRUE, /* Over 1 1-Aa */ |
|
396 TRUE, /* OverReverse 1-Ab 1 */ |
|
397 FALSE, /* In Ab 0 */ |
|
398 FALSE, /* InReverse 0 Aa */ |
|
399 FALSE, /* Out 1-Ab 0 */ |
|
400 TRUE, /* OutReverse 0 1-Aa */ |
|
401 TRUE, /* Atop Ab 1-Aa */ |
|
402 FALSE, /* AtopReverse 1-Ab Aa */ |
|
403 TRUE, /* Xor 1-Ab 1-Aa */ |
|
404 TRUE, /* Add 1 1 */ |
|
405 }; |
|
406 |
|
407 static pixman_bool_t |
|
408 get_trap_extents (pixman_op_t op, pixman_image_t *dest, |
|
409 const pixman_trapezoid_t *traps, int n_traps, |
|
410 pixman_box32_t *box) |
|
411 { |
|
412 int i; |
|
413 |
|
414 /* When the operator is such that a zero source has an |
|
415 * effect on the underlying image, we have to |
|
416 * composite across the entire destination |
|
417 */ |
|
418 if (!zero_src_has_no_effect [op]) |
|
419 { |
|
420 box->x1 = 0; |
|
421 box->y1 = 0; |
|
422 box->x2 = dest->bits.width; |
|
423 box->y2 = dest->bits.height; |
|
424 return TRUE; |
|
425 } |
|
426 |
|
427 box->x1 = INT32_MAX; |
|
428 box->y1 = INT32_MAX; |
|
429 box->x2 = INT32_MIN; |
|
430 box->y2 = INT32_MIN; |
|
431 |
|
432 for (i = 0; i < n_traps; ++i) |
|
433 { |
|
434 const pixman_trapezoid_t *trap = &(traps[i]); |
|
435 int y1, y2; |
|
436 |
|
437 if (!pixman_trapezoid_valid (trap)) |
|
438 continue; |
|
439 |
|
440 y1 = pixman_fixed_to_int (trap->top); |
|
441 if (y1 < box->y1) |
|
442 box->y1 = y1; |
|
443 |
|
444 y2 = pixman_fixed_to_int (pixman_fixed_ceil (trap->bottom)); |
|
445 if (y2 > box->y2) |
|
446 box->y2 = y2; |
|
447 |
|
448 #define EXTEND_MIN(x) \ |
|
449 if (pixman_fixed_to_int ((x)) < box->x1) \ |
|
450 box->x1 = pixman_fixed_to_int ((x)); |
|
451 #define EXTEND_MAX(x) \ |
|
452 if (pixman_fixed_to_int (pixman_fixed_ceil ((x))) > box->x2) \ |
|
453 box->x2 = pixman_fixed_to_int (pixman_fixed_ceil ((x))); |
|
454 |
|
455 #define EXTEND(x) \ |
|
456 EXTEND_MIN(x); \ |
|
457 EXTEND_MAX(x); |
|
458 |
|
459 EXTEND(trap->left.p1.x); |
|
460 EXTEND(trap->left.p2.x); |
|
461 EXTEND(trap->right.p1.x); |
|
462 EXTEND(trap->right.p2.x); |
|
463 } |
|
464 |
|
465 if (box->x1 >= box->x2 || box->y1 >= box->y2) |
|
466 return FALSE; |
|
467 |
|
468 return TRUE; |
|
469 } |
|
470 |
|
471 /* |
|
472 * pixman_composite_trapezoids() |
|
473 * |
|
474 * All the trapezoids are conceptually rendered to an infinitely big image. |
|
475 * The (0, 0) coordinates of this image are then aligned with the (x, y) |
|
476 * coordinates of the source image, and then both images are aligned with |
|
477 * the (x, y) coordinates of the destination. Then these three images are |
|
478 * composited across the entire destination. |
|
479 */ |
|
480 PIXMAN_EXPORT void |
|
481 pixman_composite_trapezoids (pixman_op_t op, |
|
482 pixman_image_t * src, |
|
483 pixman_image_t * dst, |
|
484 pixman_format_code_t mask_format, |
|
485 int x_src, |
|
486 int y_src, |
|
487 int x_dst, |
|
488 int y_dst, |
|
489 int n_traps, |
|
490 const pixman_trapezoid_t * traps) |
|
491 { |
|
492 int i; |
|
493 |
|
494 return_if_fail (PIXMAN_FORMAT_TYPE (mask_format) == PIXMAN_TYPE_A); |
|
495 |
|
496 if (n_traps <= 0) |
|
497 return; |
|
498 |
|
499 _pixman_image_validate (src); |
|
500 _pixman_image_validate (dst); |
|
501 |
|
502 if (op == PIXMAN_OP_ADD && |
|
503 (src->common.flags & FAST_PATH_IS_OPAQUE) && |
|
504 (mask_format == dst->common.extended_format_code) && |
|
505 !(dst->common.have_clip_region)) |
|
506 { |
|
507 for (i = 0; i < n_traps; ++i) |
|
508 { |
|
509 const pixman_trapezoid_t *trap = &(traps[i]); |
|
510 |
|
511 if (!pixman_trapezoid_valid (trap)) |
|
512 continue; |
|
513 |
|
514 pixman_rasterize_trapezoid (dst, trap, x_dst, y_dst); |
|
515 } |
|
516 } |
|
517 else |
|
518 { |
|
519 pixman_image_t *tmp; |
|
520 pixman_box32_t box; |
|
521 int i; |
|
522 |
|
523 if (!get_trap_extents (op, dst, traps, n_traps, &box)) |
|
524 return; |
|
525 |
|
526 if (!(tmp = pixman_image_create_bits ( |
|
527 mask_format, box.x2 - box.x1, box.y2 - box.y1, NULL, -1))) |
|
528 return; |
|
529 |
|
530 for (i = 0; i < n_traps; ++i) |
|
531 { |
|
532 const pixman_trapezoid_t *trap = &(traps[i]); |
|
533 |
|
534 if (!pixman_trapezoid_valid (trap)) |
|
535 continue; |
|
536 |
|
537 pixman_rasterize_trapezoid (tmp, trap, - box.x1, - box.y1); |
|
538 } |
|
539 |
|
540 pixman_image_composite (op, src, tmp, dst, |
|
541 x_src + box.x1, y_src + box.y1, |
|
542 0, 0, |
|
543 x_dst + box.x1, y_dst + box.y1, |
|
544 box.x2 - box.x1, box.y2 - box.y1); |
|
545 |
|
546 pixman_image_unref (tmp); |
|
547 } |
|
548 } |
|
549 |
|
550 static int |
|
551 greater_y (const pixman_point_fixed_t *a, const pixman_point_fixed_t *b) |
|
552 { |
|
553 if (a->y == b->y) |
|
554 return a->x > b->x; |
|
555 return a->y > b->y; |
|
556 } |
|
557 |
|
558 /* |
|
559 * Note that the definition of this function is a bit odd because |
|
560 * of the X coordinate space (y increasing downwards). |
|
561 */ |
|
562 static int |
|
563 clockwise (const pixman_point_fixed_t *ref, |
|
564 const pixman_point_fixed_t *a, |
|
565 const pixman_point_fixed_t *b) |
|
566 { |
|
567 pixman_point_fixed_t ad, bd; |
|
568 |
|
569 ad.x = a->x - ref->x; |
|
570 ad.y = a->y - ref->y; |
|
571 bd.x = b->x - ref->x; |
|
572 bd.y = b->y - ref->y; |
|
573 |
|
574 return ((pixman_fixed_32_32_t) bd.y * ad.x - |
|
575 (pixman_fixed_32_32_t) ad.y * bd.x) < 0; |
|
576 } |
|
577 |
|
578 static void |
|
579 triangle_to_trapezoids (const pixman_triangle_t *tri, pixman_trapezoid_t *traps) |
|
580 { |
|
581 const pixman_point_fixed_t *top, *left, *right, *tmp; |
|
582 |
|
583 top = &tri->p1; |
|
584 left = &tri->p2; |
|
585 right = &tri->p3; |
|
586 |
|
587 if (greater_y (top, left)) |
|
588 { |
|
589 tmp = left; |
|
590 left = top; |
|
591 top = tmp; |
|
592 } |
|
593 |
|
594 if (greater_y (top, right)) |
|
595 { |
|
596 tmp = right; |
|
597 right = top; |
|
598 top = tmp; |
|
599 } |
|
600 |
|
601 if (clockwise (top, right, left)) |
|
602 { |
|
603 tmp = right; |
|
604 right = left; |
|
605 left = tmp; |
|
606 } |
|
607 |
|
608 /* |
|
609 * Two cases: |
|
610 * |
|
611 * + + |
|
612 * / \ / \ |
|
613 * / \ / \ |
|
614 * / + + \ |
|
615 * / -- -- \ |
|
616 * / -- -- \ |
|
617 * / --- --- \ |
|
618 * +-- --+ |
|
619 */ |
|
620 |
|
621 traps->top = top->y; |
|
622 traps->left.p1 = *top; |
|
623 traps->left.p2 = *left; |
|
624 traps->right.p1 = *top; |
|
625 traps->right.p2 = *right; |
|
626 |
|
627 if (right->y < left->y) |
|
628 traps->bottom = right->y; |
|
629 else |
|
630 traps->bottom = left->y; |
|
631 |
|
632 traps++; |
|
633 |
|
634 *traps = *(traps - 1); |
|
635 |
|
636 if (right->y < left->y) |
|
637 { |
|
638 traps->top = right->y; |
|
639 traps->bottom = left->y; |
|
640 traps->right.p1 = *right; |
|
641 traps->right.p2 = *left; |
|
642 } |
|
643 else |
|
644 { |
|
645 traps->top = left->y; |
|
646 traps->bottom = right->y; |
|
647 traps->left.p1 = *left; |
|
648 traps->left.p2 = *right; |
|
649 } |
|
650 } |
|
651 |
|
652 static pixman_trapezoid_t * |
|
653 convert_triangles (int n_tris, const pixman_triangle_t *tris) |
|
654 { |
|
655 pixman_trapezoid_t *traps; |
|
656 int i; |
|
657 |
|
658 if (n_tris <= 0) |
|
659 return NULL; |
|
660 |
|
661 traps = pixman_malloc_ab (n_tris, 2 * sizeof (pixman_trapezoid_t)); |
|
662 if (!traps) |
|
663 return NULL; |
|
664 |
|
665 for (i = 0; i < n_tris; ++i) |
|
666 triangle_to_trapezoids (&(tris[i]), traps + 2 * i); |
|
667 |
|
668 return traps; |
|
669 } |
|
670 |
|
671 PIXMAN_EXPORT void |
|
672 pixman_composite_triangles (pixman_op_t op, |
|
673 pixman_image_t * src, |
|
674 pixman_image_t * dst, |
|
675 pixman_format_code_t mask_format, |
|
676 int x_src, |
|
677 int y_src, |
|
678 int x_dst, |
|
679 int y_dst, |
|
680 int n_tris, |
|
681 const pixman_triangle_t * tris) |
|
682 { |
|
683 pixman_trapezoid_t *traps; |
|
684 |
|
685 if ((traps = convert_triangles (n_tris, tris))) |
|
686 { |
|
687 pixman_composite_trapezoids (op, src, dst, mask_format, |
|
688 x_src, y_src, x_dst, y_dst, |
|
689 n_tris * 2, traps); |
|
690 |
|
691 free (traps); |
|
692 } |
|
693 } |
|
694 |
|
695 PIXMAN_EXPORT void |
|
696 pixman_add_triangles (pixman_image_t *image, |
|
697 int32_t x_off, |
|
698 int32_t y_off, |
|
699 int n_tris, |
|
700 const pixman_triangle_t *tris) |
|
701 { |
|
702 pixman_trapezoid_t *traps; |
|
703 |
|
704 if ((traps = convert_triangles (n_tris, tris))) |
|
705 { |
|
706 pixman_add_trapezoids (image, x_off, y_off, |
|
707 n_tris * 2, traps); |
|
708 |
|
709 free (traps); |
|
710 } |
|
711 } |