gfx/cairo/libpixman/src/pixman-trap.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial