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

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/cairo/libpixman/src/pixman-trap.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,711 @@
     1.4 +/*
     1.5 + * Copyright © 2002 Keith Packard, member of The XFree86 Project, Inc.
     1.6 + * Copyright © 2004 Keith Packard
     1.7 + *
     1.8 + * Permission to use, copy, modify, distribute, and sell this software and its
     1.9 + * documentation for any purpose is hereby granted without fee, provided that
    1.10 + * the above copyright notice appear in all copies and that both that
    1.11 + * copyright notice and this permission notice appear in supporting
    1.12 + * documentation, and that the name of Keith Packard not be used in
    1.13 + * advertising or publicity pertaining to distribution of the software without
    1.14 + * specific, written prior permission.  Keith Packard makes no
    1.15 + * representations about the suitability of this software for any purpose.  It
    1.16 + * is provided "as is" without express or implied warranty.
    1.17 + *
    1.18 + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
    1.19 + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
    1.20 + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
    1.21 + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
    1.22 + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
    1.23 + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
    1.24 + * PERFORMANCE OF THIS SOFTWARE.
    1.25 + */
    1.26 +
    1.27 +#ifdef HAVE_CONFIG_H
    1.28 +#include <config.h>
    1.29 +#endif
    1.30 +
    1.31 +#include <stdio.h>
    1.32 +#include <stdlib.h>
    1.33 +#include "pixman-private.h"
    1.34 +
    1.35 +/*
    1.36 + * Compute the smallest value greater than or equal to y which is on a
    1.37 + * grid row.
    1.38 + */
    1.39 +
    1.40 +PIXMAN_EXPORT pixman_fixed_t
    1.41 +pixman_sample_ceil_y (pixman_fixed_t y, int n)
    1.42 +{
    1.43 +    pixman_fixed_t f = pixman_fixed_frac (y);
    1.44 +    pixman_fixed_t i = pixman_fixed_floor (y);
    1.45 +
    1.46 +    f = DIV (f - Y_FRAC_FIRST (n) + (STEP_Y_SMALL (n) - pixman_fixed_e), STEP_Y_SMALL (n)) * STEP_Y_SMALL (n) +
    1.47 +	Y_FRAC_FIRST (n);
    1.48 +    
    1.49 +    if (f > Y_FRAC_LAST (n))
    1.50 +    {
    1.51 +	if (pixman_fixed_to_int (i) == 0x7fff)
    1.52 +	{
    1.53 +	    f = 0xffff; /* saturate */
    1.54 +	}
    1.55 +	else
    1.56 +	{
    1.57 +	    f = Y_FRAC_FIRST (n);
    1.58 +	    i += pixman_fixed_1;
    1.59 +	}
    1.60 +    }
    1.61 +    return (i | f);
    1.62 +}
    1.63 +
    1.64 +/*
    1.65 + * Compute the largest value strictly less than y which is on a
    1.66 + * grid row.
    1.67 + */
    1.68 +PIXMAN_EXPORT pixman_fixed_t
    1.69 +pixman_sample_floor_y (pixman_fixed_t y,
    1.70 +                       int            n)
    1.71 +{
    1.72 +    pixman_fixed_t f = pixman_fixed_frac (y);
    1.73 +    pixman_fixed_t i = pixman_fixed_floor (y);
    1.74 +
    1.75 +    f = DIV (f - pixman_fixed_e - Y_FRAC_FIRST (n), STEP_Y_SMALL (n)) * STEP_Y_SMALL (n) +
    1.76 +	Y_FRAC_FIRST (n);
    1.77 +
    1.78 +    if (f < Y_FRAC_FIRST (n))
    1.79 +    {
    1.80 +	if (pixman_fixed_to_int (i) == 0x8000)
    1.81 +	{
    1.82 +	    f = 0; /* saturate */
    1.83 +	}
    1.84 +	else
    1.85 +	{
    1.86 +	    f = Y_FRAC_LAST (n);
    1.87 +	    i -= pixman_fixed_1;
    1.88 +	}
    1.89 +    }
    1.90 +    return (i | f);
    1.91 +}
    1.92 +
    1.93 +/*
    1.94 + * Step an edge by any amount (including negative values)
    1.95 + */
    1.96 +PIXMAN_EXPORT void
    1.97 +pixman_edge_step (pixman_edge_t *e,
    1.98 +                  int            n)
    1.99 +{
   1.100 +    pixman_fixed_48_16_t ne;
   1.101 +
   1.102 +    e->x += n * e->stepx;
   1.103 +
   1.104 +    ne = e->e + n * (pixman_fixed_48_16_t) e->dx;
   1.105 +
   1.106 +    if (n >= 0)
   1.107 +    {
   1.108 +	if (ne > 0)
   1.109 +	{
   1.110 +	    int nx = (ne + e->dy - 1) / e->dy;
   1.111 +	    e->e = ne - nx * (pixman_fixed_48_16_t) e->dy;
   1.112 +	    e->x += nx * e->signdx;
   1.113 +	}
   1.114 +    }
   1.115 +    else
   1.116 +    {
   1.117 +	if (ne <= -e->dy)
   1.118 +	{
   1.119 +	    int nx = (-ne) / e->dy;
   1.120 +	    e->e = ne + nx * (pixman_fixed_48_16_t) e->dy;
   1.121 +	    e->x -= nx * e->signdx;
   1.122 +	}
   1.123 +    }
   1.124 +}
   1.125 +
   1.126 +/*
   1.127 + * A private routine to initialize the multi-step
   1.128 + * elements of an edge structure
   1.129 + */
   1.130 +static void
   1.131 +_pixman_edge_multi_init (pixman_edge_t * e,
   1.132 +                         int             n,
   1.133 +                         pixman_fixed_t *stepx_p,
   1.134 +                         pixman_fixed_t *dx_p)
   1.135 +{
   1.136 +    pixman_fixed_t stepx;
   1.137 +    pixman_fixed_48_16_t ne;
   1.138 +
   1.139 +    ne = n * (pixman_fixed_48_16_t) e->dx;
   1.140 +    stepx = n * e->stepx;
   1.141 +
   1.142 +    if (ne > 0)
   1.143 +    {
   1.144 +	int nx = ne / e->dy;
   1.145 +	ne -= nx * (pixman_fixed_48_16_t)e->dy;
   1.146 +	stepx += nx * e->signdx;
   1.147 +    }
   1.148 +
   1.149 +    *dx_p = ne;
   1.150 +    *stepx_p = stepx;
   1.151 +}
   1.152 +
   1.153 +/*
   1.154 + * Initialize one edge structure given the line endpoints and a
   1.155 + * starting y value
   1.156 + */
   1.157 +PIXMAN_EXPORT void
   1.158 +pixman_edge_init (pixman_edge_t *e,
   1.159 +                  int            n,
   1.160 +                  pixman_fixed_t y_start,
   1.161 +                  pixman_fixed_t x_top,
   1.162 +                  pixman_fixed_t y_top,
   1.163 +                  pixman_fixed_t x_bot,
   1.164 +                  pixman_fixed_t y_bot)
   1.165 +{
   1.166 +    pixman_fixed_t dx, dy;
   1.167 +
   1.168 +    e->x = x_top;
   1.169 +    e->e = 0;
   1.170 +    dx = x_bot - x_top;
   1.171 +    dy = y_bot - y_top;
   1.172 +    e->dy = dy;
   1.173 +    e->dx = 0;
   1.174 +
   1.175 +    if (dy)
   1.176 +    {
   1.177 +	if (dx >= 0)
   1.178 +	{
   1.179 +	    e->signdx = 1;
   1.180 +	    e->stepx = dx / dy;
   1.181 +	    e->dx = dx % dy;
   1.182 +	    e->e = -dy;
   1.183 +	}
   1.184 +	else
   1.185 +	{
   1.186 +	    e->signdx = -1;
   1.187 +	    e->stepx = -(-dx / dy);
   1.188 +	    e->dx = -dx % dy;
   1.189 +	    e->e = 0;
   1.190 +	}
   1.191 +
   1.192 +	_pixman_edge_multi_init (e, STEP_Y_SMALL (n),
   1.193 +				 &e->stepx_small, &e->dx_small);
   1.194 +
   1.195 +	_pixman_edge_multi_init (e, STEP_Y_BIG (n),
   1.196 +				 &e->stepx_big, &e->dx_big);
   1.197 +    }
   1.198 +    pixman_edge_step (e, y_start - y_top);
   1.199 +}
   1.200 +
   1.201 +/*
   1.202 + * Initialize one edge structure given a line, starting y value
   1.203 + * and a pixel offset for the line
   1.204 + */
   1.205 +PIXMAN_EXPORT void
   1.206 +pixman_line_fixed_edge_init (pixman_edge_t *            e,
   1.207 +                             int                        n,
   1.208 +                             pixman_fixed_t             y,
   1.209 +                             const pixman_line_fixed_t *line,
   1.210 +                             int                        x_off,
   1.211 +                             int                        y_off)
   1.212 +{
   1.213 +    pixman_fixed_t x_off_fixed = pixman_int_to_fixed (x_off);
   1.214 +    pixman_fixed_t y_off_fixed = pixman_int_to_fixed (y_off);
   1.215 +    const pixman_point_fixed_t *top, *bot;
   1.216 +
   1.217 +    if (line->p1.y <= line->p2.y)
   1.218 +    {
   1.219 +	top = &line->p1;
   1.220 +	bot = &line->p2;
   1.221 +    }
   1.222 +    else
   1.223 +    {
   1.224 +	top = &line->p2;
   1.225 +	bot = &line->p1;
   1.226 +    }
   1.227 +    
   1.228 +    pixman_edge_init (e, n, y,
   1.229 +                      top->x + x_off_fixed,
   1.230 +                      top->y + y_off_fixed,
   1.231 +                      bot->x + x_off_fixed,
   1.232 +                      bot->y + y_off_fixed);
   1.233 +}
   1.234 +
   1.235 +PIXMAN_EXPORT void
   1.236 +pixman_add_traps (pixman_image_t *     image,
   1.237 +                  int16_t              x_off,
   1.238 +                  int16_t              y_off,
   1.239 +                  int                  ntrap,
   1.240 +                  const pixman_trap_t *traps)
   1.241 +{
   1.242 +    int bpp;
   1.243 +    int height;
   1.244 +
   1.245 +    pixman_fixed_t x_off_fixed;
   1.246 +    pixman_fixed_t y_off_fixed;
   1.247 +    pixman_edge_t l, r;
   1.248 +    pixman_fixed_t t, b;
   1.249 +
   1.250 +    _pixman_image_validate (image);
   1.251 +    
   1.252 +    height = image->bits.height;
   1.253 +    bpp = PIXMAN_FORMAT_BPP (image->bits.format);
   1.254 +
   1.255 +    x_off_fixed = pixman_int_to_fixed (x_off);
   1.256 +    y_off_fixed = pixman_int_to_fixed (y_off);
   1.257 +
   1.258 +    while (ntrap--)
   1.259 +    {
   1.260 +	t = traps->top.y + y_off_fixed;
   1.261 +	if (t < 0)
   1.262 +	    t = 0;
   1.263 +	t = pixman_sample_ceil_y (t, bpp);
   1.264 +
   1.265 +	b = traps->bot.y + y_off_fixed;
   1.266 +	if (pixman_fixed_to_int (b) >= height)
   1.267 +	    b = pixman_int_to_fixed (height) - 1;
   1.268 +	b = pixman_sample_floor_y (b, bpp);
   1.269 +
   1.270 +	if (b >= t)
   1.271 +	{
   1.272 +	    /* initialize edge walkers */
   1.273 +	    pixman_edge_init (&l, bpp, t,
   1.274 +	                      traps->top.l + x_off_fixed,
   1.275 +	                      traps->top.y + y_off_fixed,
   1.276 +	                      traps->bot.l + x_off_fixed,
   1.277 +	                      traps->bot.y + y_off_fixed);
   1.278 +
   1.279 +	    pixman_edge_init (&r, bpp, t,
   1.280 +	                      traps->top.r + x_off_fixed,
   1.281 +	                      traps->top.y + y_off_fixed,
   1.282 +	                      traps->bot.r + x_off_fixed,
   1.283 +	                      traps->bot.y + y_off_fixed);
   1.284 +
   1.285 +	    pixman_rasterize_edges (image, &l, &r, t, b);
   1.286 +	}
   1.287 +
   1.288 +	traps++;
   1.289 +    }
   1.290 +}
   1.291 +
   1.292 +#if 0
   1.293 +static void
   1.294 +dump_image (pixman_image_t *image,
   1.295 +            const char *    title)
   1.296 +{
   1.297 +    int i, j;
   1.298 +
   1.299 +    if (!image->type == BITS)
   1.300 +	printf ("%s is not a regular image\n", title);
   1.301 +
   1.302 +    if (!image->bits.format == PIXMAN_a8)
   1.303 +	printf ("%s is not an alpha mask\n", title);
   1.304 +
   1.305 +    printf ("\n\n\n%s: \n", title);
   1.306 +
   1.307 +    for (i = 0; i < image->bits.height; ++i)
   1.308 +    {
   1.309 +	uint8_t *line =
   1.310 +	    (uint8_t *)&(image->bits.bits[i * image->bits.rowstride]);
   1.311 +
   1.312 +	for (j = 0; j < image->bits.width; ++j)
   1.313 +	    printf ("%c", line[j] ? '#' : ' ');
   1.314 +
   1.315 +	printf ("\n");
   1.316 +    }
   1.317 +}
   1.318 +#endif
   1.319 +
   1.320 +PIXMAN_EXPORT void
   1.321 +pixman_add_trapezoids (pixman_image_t *          image,
   1.322 +                       int16_t                   x_off,
   1.323 +                       int                       y_off,
   1.324 +                       int                       ntraps,
   1.325 +                       const pixman_trapezoid_t *traps)
   1.326 +{
   1.327 +    int i;
   1.328 +
   1.329 +#if 0
   1.330 +    dump_image (image, "before");
   1.331 +#endif
   1.332 +
   1.333 +    for (i = 0; i < ntraps; ++i)
   1.334 +    {
   1.335 +	const pixman_trapezoid_t *trap = &(traps[i]);
   1.336 +
   1.337 +	if (!pixman_trapezoid_valid (trap))
   1.338 +	    continue;
   1.339 +
   1.340 +	pixman_rasterize_trapezoid (image, trap, x_off, y_off);
   1.341 +    }
   1.342 +
   1.343 +#if 0
   1.344 +    dump_image (image, "after");
   1.345 +#endif
   1.346 +}
   1.347 +
   1.348 +PIXMAN_EXPORT void
   1.349 +pixman_rasterize_trapezoid (pixman_image_t *          image,
   1.350 +                            const pixman_trapezoid_t *trap,
   1.351 +                            int                       x_off,
   1.352 +                            int                       y_off)
   1.353 +{
   1.354 +    int bpp;
   1.355 +    int height;
   1.356 +
   1.357 +    pixman_fixed_t y_off_fixed;
   1.358 +    pixman_edge_t l, r;
   1.359 +    pixman_fixed_t t, b;
   1.360 +
   1.361 +    return_if_fail (image->type == BITS);
   1.362 +
   1.363 +    _pixman_image_validate (image);
   1.364 +    
   1.365 +    if (!pixman_trapezoid_valid (trap))
   1.366 +	return;
   1.367 +
   1.368 +    height = image->bits.height;
   1.369 +    bpp = PIXMAN_FORMAT_BPP (image->bits.format);
   1.370 +
   1.371 +    y_off_fixed = pixman_int_to_fixed (y_off);
   1.372 +
   1.373 +    t = trap->top + y_off_fixed;
   1.374 +    if (t < 0)
   1.375 +	t = 0;
   1.376 +    t = pixman_sample_ceil_y (t, bpp);
   1.377 +
   1.378 +    b = trap->bottom + y_off_fixed;
   1.379 +    if (pixman_fixed_to_int (b) >= height)
   1.380 +	b = pixman_int_to_fixed (height) - 1;
   1.381 +    b = pixman_sample_floor_y (b, bpp);
   1.382 +    
   1.383 +    if (b >= t)
   1.384 +    {
   1.385 +	/* initialize edge walkers */
   1.386 +	pixman_line_fixed_edge_init (&l, bpp, t, &trap->left, x_off, y_off);
   1.387 +	pixman_line_fixed_edge_init (&r, bpp, t, &trap->right, x_off, y_off);
   1.388 +
   1.389 +	pixman_rasterize_edges (image, &l, &r, t, b);
   1.390 +    }
   1.391 +}
   1.392 +
   1.393 +static const pixman_bool_t zero_src_has_no_effect[PIXMAN_N_OPERATORS] =
   1.394 +{
   1.395 +    FALSE,	/* Clear		0			0    */
   1.396 +    FALSE,	/* Src			1			0    */
   1.397 +    TRUE,	/* Dst			0			1    */
   1.398 +    TRUE,	/* Over			1			1-Aa */
   1.399 +    TRUE,	/* OverReverse		1-Ab			1    */
   1.400 +    FALSE,	/* In			Ab			0    */
   1.401 +    FALSE,	/* InReverse		0			Aa   */
   1.402 +    FALSE,	/* Out			1-Ab			0    */
   1.403 +    TRUE,	/* OutReverse		0			1-Aa */
   1.404 +    TRUE,	/* Atop			Ab			1-Aa */
   1.405 +    FALSE,	/* AtopReverse		1-Ab			Aa   */
   1.406 +    TRUE,	/* Xor			1-Ab			1-Aa */
   1.407 +    TRUE,	/* Add			1			1    */
   1.408 +};
   1.409 +
   1.410 +static pixman_bool_t
   1.411 +get_trap_extents (pixman_op_t op, pixman_image_t *dest,
   1.412 +		  const pixman_trapezoid_t *traps, int n_traps,
   1.413 +		  pixman_box32_t *box)
   1.414 +{
   1.415 +    int i;
   1.416 +
   1.417 +    /* When the operator is such that a zero source has an
   1.418 +     * effect on the underlying image, we have to
   1.419 +     * composite across the entire destination
   1.420 +     */
   1.421 +    if (!zero_src_has_no_effect [op])
   1.422 +    {
   1.423 +	box->x1 = 0;
   1.424 +	box->y1 = 0;
   1.425 +	box->x2 = dest->bits.width;
   1.426 +	box->y2 = dest->bits.height;
   1.427 +	return TRUE;
   1.428 +    }
   1.429 +    
   1.430 +    box->x1 = INT32_MAX;
   1.431 +    box->y1 = INT32_MAX;
   1.432 +    box->x2 = INT32_MIN;
   1.433 +    box->y2 = INT32_MIN;
   1.434 +	
   1.435 +    for (i = 0; i < n_traps; ++i)
   1.436 +    {
   1.437 +	const pixman_trapezoid_t *trap = &(traps[i]);
   1.438 +	int y1, y2;
   1.439 +	    
   1.440 +	if (!pixman_trapezoid_valid (trap))
   1.441 +	    continue;
   1.442 +	    
   1.443 +	y1 = pixman_fixed_to_int (trap->top);
   1.444 +	if (y1 < box->y1)
   1.445 +	    box->y1 = y1;
   1.446 +	    
   1.447 +	y2 = pixman_fixed_to_int (pixman_fixed_ceil (trap->bottom));
   1.448 +	if (y2 > box->y2)
   1.449 +	    box->y2 = y2;
   1.450 +	    
   1.451 +#define EXTEND_MIN(x)							\
   1.452 +	if (pixman_fixed_to_int ((x)) < box->x1)			\
   1.453 +	    box->x1 = pixman_fixed_to_int ((x));
   1.454 +#define EXTEND_MAX(x)							\
   1.455 +	if (pixman_fixed_to_int (pixman_fixed_ceil ((x))) > box->x2)	\
   1.456 +	    box->x2 = pixman_fixed_to_int (pixman_fixed_ceil ((x)));
   1.457 +	    
   1.458 +#define EXTEND(x)							\
   1.459 +	EXTEND_MIN(x);							\
   1.460 +	EXTEND_MAX(x);
   1.461 +	    
   1.462 +	EXTEND(trap->left.p1.x);
   1.463 +	EXTEND(trap->left.p2.x);
   1.464 +	EXTEND(trap->right.p1.x);
   1.465 +	EXTEND(trap->right.p2.x);
   1.466 +    }
   1.467 +	
   1.468 +    if (box->x1 >= box->x2 || box->y1 >= box->y2)
   1.469 +	return FALSE;
   1.470 +
   1.471 +    return TRUE;
   1.472 +}
   1.473 +
   1.474 +/*
   1.475 + * pixman_composite_trapezoids()
   1.476 + *
   1.477 + * All the trapezoids are conceptually rendered to an infinitely big image.
   1.478 + * The (0, 0) coordinates of this image are then aligned with the (x, y)
   1.479 + * coordinates of the source image, and then both images are aligned with
   1.480 + * the (x, y) coordinates of the destination. Then these three images are
   1.481 + * composited across the entire destination.
   1.482 + */
   1.483 +PIXMAN_EXPORT void
   1.484 +pixman_composite_trapezoids (pixman_op_t		op,
   1.485 +			     pixman_image_t *		src,
   1.486 +			     pixman_image_t *		dst,
   1.487 +			     pixman_format_code_t	mask_format,
   1.488 +			     int			x_src,
   1.489 +			     int			y_src,
   1.490 +			     int			x_dst,
   1.491 +			     int			y_dst,
   1.492 +			     int			n_traps,
   1.493 +			     const pixman_trapezoid_t *	traps)
   1.494 +{
   1.495 +    int i;
   1.496 +
   1.497 +    return_if_fail (PIXMAN_FORMAT_TYPE (mask_format) == PIXMAN_TYPE_A);
   1.498 +    
   1.499 +    if (n_traps <= 0)
   1.500 +	return;
   1.501 +
   1.502 +    _pixman_image_validate (src);
   1.503 +    _pixman_image_validate (dst);
   1.504 +
   1.505 +    if (op == PIXMAN_OP_ADD &&
   1.506 +	(src->common.flags & FAST_PATH_IS_OPAQUE)		&&
   1.507 +	(mask_format == dst->common.extended_format_code)	&&
   1.508 +	!(dst->common.have_clip_region))
   1.509 +    {
   1.510 +	for (i = 0; i < n_traps; ++i)
   1.511 +	{
   1.512 +	    const pixman_trapezoid_t *trap = &(traps[i]);
   1.513 +	    
   1.514 +	    if (!pixman_trapezoid_valid (trap))
   1.515 +		continue;
   1.516 +	    
   1.517 +	    pixman_rasterize_trapezoid (dst, trap, x_dst, y_dst);
   1.518 +	}
   1.519 +    }
   1.520 +    else
   1.521 +    {
   1.522 +	pixman_image_t *tmp;
   1.523 +	pixman_box32_t box;
   1.524 +	int i;
   1.525 +
   1.526 +	if (!get_trap_extents (op, dst, traps, n_traps, &box))
   1.527 +	    return;
   1.528 +	
   1.529 +	if (!(tmp = pixman_image_create_bits (
   1.530 +		  mask_format, box.x2 - box.x1, box.y2 - box.y1, NULL, -1)))
   1.531 +	    return;
   1.532 +	
   1.533 +	for (i = 0; i < n_traps; ++i)
   1.534 +	{
   1.535 +	    const pixman_trapezoid_t *trap = &(traps[i]);
   1.536 +	    
   1.537 +	    if (!pixman_trapezoid_valid (trap))
   1.538 +		continue;
   1.539 +	    
   1.540 +	    pixman_rasterize_trapezoid (tmp, trap, - box.x1, - box.y1);
   1.541 +	}
   1.542 +	
   1.543 +	pixman_image_composite (op, src, tmp, dst,
   1.544 +				x_src + box.x1, y_src + box.y1,
   1.545 +				0, 0,
   1.546 +				x_dst + box.x1, y_dst + box.y1,
   1.547 +				box.x2 - box.x1, box.y2 - box.y1);
   1.548 +	
   1.549 +	pixman_image_unref (tmp);
   1.550 +    }
   1.551 +}
   1.552 +
   1.553 +static int
   1.554 +greater_y (const pixman_point_fixed_t *a, const pixman_point_fixed_t *b)
   1.555 +{
   1.556 +    if (a->y == b->y)
   1.557 +	return a->x > b->x;
   1.558 +    return a->y > b->y;
   1.559 +}
   1.560 +
   1.561 +/*
   1.562 + * Note that the definition of this function is a bit odd because
   1.563 + * of the X coordinate space (y increasing downwards).
   1.564 + */
   1.565 +static int
   1.566 +clockwise (const pixman_point_fixed_t *ref,
   1.567 +	   const pixman_point_fixed_t *a,
   1.568 +	   const pixman_point_fixed_t *b)
   1.569 +{
   1.570 +    pixman_point_fixed_t	ad, bd;
   1.571 +
   1.572 +    ad.x = a->x - ref->x;
   1.573 +    ad.y = a->y - ref->y;
   1.574 +    bd.x = b->x - ref->x;
   1.575 +    bd.y = b->y - ref->y;
   1.576 +
   1.577 +    return ((pixman_fixed_32_32_t) bd.y * ad.x -
   1.578 +	    (pixman_fixed_32_32_t) ad.y * bd.x) < 0;
   1.579 +}
   1.580 +
   1.581 +static void
   1.582 +triangle_to_trapezoids (const pixman_triangle_t *tri, pixman_trapezoid_t *traps)
   1.583 +{
   1.584 +    const pixman_point_fixed_t *top, *left, *right, *tmp;
   1.585 +
   1.586 +    top = &tri->p1;
   1.587 +    left = &tri->p2;
   1.588 +    right = &tri->p3;
   1.589 +
   1.590 +    if (greater_y (top, left))
   1.591 +    {
   1.592 +	tmp = left;
   1.593 +	left = top;
   1.594 +	top = tmp;
   1.595 +    }
   1.596 +
   1.597 +    if (greater_y (top, right))
   1.598 +    {
   1.599 +	tmp = right;
   1.600 +	right = top;
   1.601 +	top = tmp;
   1.602 +    }
   1.603 +
   1.604 +    if (clockwise (top, right, left))
   1.605 +    {
   1.606 +	tmp = right;
   1.607 +	right = left;
   1.608 +	left = tmp;
   1.609 +    }
   1.610 +    
   1.611 +    /*
   1.612 +     * Two cases:
   1.613 +     *
   1.614 +     *		+		+
   1.615 +     *	       / \             / \
   1.616 +     *	      /   \           /	  \
   1.617 +     *	     /     +         +	   \
   1.618 +     *      /    --           --    \
   1.619 +     *     /   --               --   \
   1.620 +     *    / ---                   --- \
   1.621 +     *	 +--                         --+
   1.622 +     */
   1.623 +
   1.624 +    traps->top = top->y;
   1.625 +    traps->left.p1 = *top;
   1.626 +    traps->left.p2 = *left;
   1.627 +    traps->right.p1 = *top;
   1.628 +    traps->right.p2 = *right;
   1.629 +
   1.630 +    if (right->y < left->y)
   1.631 +	traps->bottom = right->y;
   1.632 +    else
   1.633 +	traps->bottom = left->y;
   1.634 +
   1.635 +    traps++;
   1.636 +
   1.637 +    *traps = *(traps - 1);
   1.638 +    
   1.639 +    if (right->y < left->y)
   1.640 +    {
   1.641 +	traps->top = right->y;
   1.642 +	traps->bottom = left->y;
   1.643 +	traps->right.p1 = *right;
   1.644 +	traps->right.p2 = *left;
   1.645 +    }
   1.646 +    else
   1.647 +    {
   1.648 +	traps->top = left->y;
   1.649 +	traps->bottom = right->y;
   1.650 +	traps->left.p1 = *left;
   1.651 +	traps->left.p2 = *right;
   1.652 +    }
   1.653 +}
   1.654 +
   1.655 +static pixman_trapezoid_t *
   1.656 +convert_triangles (int n_tris, const pixman_triangle_t *tris)
   1.657 +{
   1.658 +    pixman_trapezoid_t *traps;
   1.659 +    int i;
   1.660 +
   1.661 +    if (n_tris <= 0)
   1.662 +	return NULL;
   1.663 +    
   1.664 +    traps = pixman_malloc_ab (n_tris, 2 * sizeof (pixman_trapezoid_t));
   1.665 +    if (!traps)
   1.666 +	return NULL;
   1.667 +
   1.668 +    for (i = 0; i < n_tris; ++i)
   1.669 +	triangle_to_trapezoids (&(tris[i]), traps + 2 * i);
   1.670 +
   1.671 +    return traps;
   1.672 +}
   1.673 +
   1.674 +PIXMAN_EXPORT void
   1.675 +pixman_composite_triangles (pixman_op_t			op,
   1.676 +			    pixman_image_t *		src,
   1.677 +			    pixman_image_t *		dst,
   1.678 +			    pixman_format_code_t	mask_format,
   1.679 +			    int				x_src,
   1.680 +			    int				y_src,
   1.681 +			    int				x_dst,
   1.682 +			    int				y_dst,
   1.683 +			    int				n_tris,
   1.684 +			    const pixman_triangle_t *	tris)
   1.685 +{
   1.686 +    pixman_trapezoid_t *traps;
   1.687 +
   1.688 +    if ((traps = convert_triangles (n_tris, tris)))
   1.689 +    {
   1.690 +	pixman_composite_trapezoids (op, src, dst, mask_format,
   1.691 +				     x_src, y_src, x_dst, y_dst,
   1.692 +				     n_tris * 2, traps);
   1.693 +	
   1.694 +	free (traps);
   1.695 +    }
   1.696 +}
   1.697 +
   1.698 +PIXMAN_EXPORT void
   1.699 +pixman_add_triangles (pixman_image_t          *image,
   1.700 +		      int32_t	               x_off,
   1.701 +		      int32_t	               y_off,
   1.702 +		      int	               n_tris,
   1.703 +		      const pixman_triangle_t *tris)
   1.704 +{
   1.705 +    pixman_trapezoid_t *traps;
   1.706 +
   1.707 +    if ((traps = convert_triangles (n_tris, tris)))
   1.708 +    {
   1.709 +	pixman_add_trapezoids (image, x_off, y_off,
   1.710 +			       n_tris * 2, traps);
   1.711 +
   1.712 +	free (traps);
   1.713 +    }
   1.714 +}

mercurial