diff options
Diffstat (limited to 'pixman/pixman/pixman-trap.c')
-rw-r--r-- | pixman/pixman/pixman-trap.c | 414 |
1 files changed, 259 insertions, 155 deletions
diff --git a/pixman/pixman/pixman-trap.c b/pixman/pixman/pixman-trap.c index 28dacafcc..4d7a90a36 100644 --- a/pixman/pixman/pixman-trap.c +++ b/pixman/pixman/pixman-trap.c @@ -27,30 +27,228 @@ #include <stdio.h> #include "pixman-private.h" -typedef uint32_t FbBits; +/* + * Compute the smallest value no less than y which is on a + * grid row + */ + +PIXMAN_EXPORT pixman_fixed_t +pixman_sample_ceil_y (pixman_fixed_t y, int n) +{ + pixman_fixed_t f = pixman_fixed_frac (y); + pixman_fixed_t i = pixman_fixed_floor (y); + + f = ((f + Y_FRAC_FIRST (n)) / STEP_Y_SMALL (n)) * STEP_Y_SMALL (n) + + Y_FRAC_FIRST (n); + + if (f > Y_FRAC_LAST (n)) + { + if (pixman_fixed_to_int (i) == 0x7fff) + { + f = 0xffff; /* saturate */ + } + else + { + f = Y_FRAC_FIRST (n); + i += pixman_fixed_1; + } + } + return (i | f); +} + +/* + * Compute the largest value no greater than y which is on a + * grid row + */ +PIXMAN_EXPORT pixman_fixed_t +pixman_sample_floor_y (pixman_fixed_t y, + int n) +{ + pixman_fixed_t f = pixman_fixed_frac (y); + pixman_fixed_t i = pixman_fixed_floor (y); + + f = DIV (f - Y_FRAC_FIRST (n), STEP_Y_SMALL (n)) * STEP_Y_SMALL (n) + + Y_FRAC_FIRST (n); + + if (f < Y_FRAC_FIRST (n)) + { + if (pixman_fixed_to_int (i) == 0x8000) + { + f = 0; /* saturate */ + } + else + { + f = Y_FRAC_LAST (n); + i -= pixman_fixed_1; + } + } + return (i | f); +} + +/* + * Step an edge by any amount (including negative values) + */ +PIXMAN_EXPORT void +pixman_edge_step (pixman_edge_t *e, + int n) +{ + pixman_fixed_48_16_t ne; + + e->x += n * e->stepx; + + ne = e->e + n * (pixman_fixed_48_16_t) e->dx; + + if (n >= 0) + { + if (ne > 0) + { + int nx = (ne + e->dy - 1) / e->dy; + e->e = ne - nx * (pixman_fixed_48_16_t) e->dy; + e->x += nx * e->signdx; + } + } + else + { + if (ne <= -e->dy) + { + int nx = (-ne) / e->dy; + e->e = ne + nx * (pixman_fixed_48_16_t) e->dy; + e->x -= nx * e->signdx; + } + } +} + +/* + * A private routine to initialize the multi-step + * elements of an edge structure + */ +static void +_pixman_edge_multi_init (pixman_edge_t * e, + int n, + pixman_fixed_t *stepx_p, + pixman_fixed_t *dx_p) +{ + pixman_fixed_t stepx; + pixman_fixed_48_16_t ne; + + ne = n * (pixman_fixed_48_16_t) e->dx; + stepx = n * e->stepx; + + if (ne > 0) + { + int nx = ne / e->dy; + ne -= nx * e->dy; + stepx += nx * e->signdx; + } + + *dx_p = ne; + *stepx_p = stepx; +} + +/* + * Initialize one edge structure given the line endpoints and a + * starting y value + */ +PIXMAN_EXPORT void +pixman_edge_init (pixman_edge_t *e, + int n, + pixman_fixed_t y_start, + pixman_fixed_t x_top, + pixman_fixed_t y_top, + pixman_fixed_t x_bot, + pixman_fixed_t y_bot) +{ + pixman_fixed_t dx, dy; + + e->x = x_top; + e->e = 0; + dx = x_bot - x_top; + dy = y_bot - y_top; + e->dy = dy; + e->dx = 0; + + if (dy) + { + if (dx >= 0) + { + e->signdx = 1; + e->stepx = dx / dy; + e->dx = dx % dy; + e->e = -dy; + } + else + { + e->signdx = -1; + e->stepx = -(-dx / dy); + e->dx = -dx % dy; + e->e = 0; + } + + _pixman_edge_multi_init (e, STEP_Y_SMALL (n), + &e->stepx_small, &e->dx_small); + + _pixman_edge_multi_init (e, STEP_Y_BIG (n), + &e->stepx_big, &e->dx_big); + } + pixman_edge_step (e, y_start - y_top); +} + +/* + * Initialize one edge structure given a line, starting y value + * and a pixel offset for the line + */ +PIXMAN_EXPORT void +pixman_line_fixed_edge_init (pixman_edge_t * e, + int n, + pixman_fixed_t y, + const pixman_line_fixed_t *line, + int x_off, + int y_off) +{ + pixman_fixed_t x_off_fixed = pixman_int_to_fixed (x_off); + pixman_fixed_t y_off_fixed = pixman_int_to_fixed (y_off); + const pixman_point_fixed_t *top, *bot; + + if (line->p1.y <= line->p2.y) + { + top = &line->p1; + bot = &line->p2; + } + else + { + top = &line->p2; + bot = &line->p1; + } + + pixman_edge_init (e, n, y, + top->x + x_off_fixed, + top->y + y_off_fixed, + bot->x + x_off_fixed, + bot->y + y_off_fixed); +} PIXMAN_EXPORT void -pixman_add_traps (pixman_image_t * image, - int16_t x_off, - int16_t y_off, - int ntrap, - pixman_trap_t *traps) +pixman_add_traps (pixman_image_t * image, + int16_t x_off, + int16_t y_off, + int ntrap, + pixman_trap_t * traps) { - int bpp; - int width; - int height; + int bpp; + int width; + int height; - pixman_fixed_t x_off_fixed; - pixman_fixed_t y_off_fixed; - pixman_edge_t l, r; - pixman_fixed_t t, b; + pixman_fixed_t x_off_fixed; + pixman_fixed_t y_off_fixed; + pixman_edge_t l, r; + pixman_fixed_t t, b; width = image->bits.width; height = image->bits.height; bpp = PIXMAN_FORMAT_BPP (image->bits.format); - - x_off_fixed = pixman_int_to_fixed(x_off); - y_off_fixed = pixman_int_to_fixed(y_off); + + x_off_fixed = pixman_int_to_fixed (x_off); + y_off_fixed = pixman_int_to_fixed (y_off); while (ntrap--) { @@ -58,83 +256,82 @@ pixman_add_traps (pixman_image_t * image, if (t < 0) t = 0; t = pixman_sample_ceil_y (t, bpp); - + b = traps->bot.y + y_off_fixed; if (pixman_fixed_to_int (b) >= height) b = pixman_int_to_fixed (height) - 1; b = pixman_sample_floor_y (b, bpp); - + if (b >= t) { /* initialize edge walkers */ pixman_edge_init (&l, bpp, t, - traps->top.l + x_off_fixed, - traps->top.y + y_off_fixed, - traps->bot.l + x_off_fixed, - traps->bot.y + y_off_fixed); - + traps->top.l + x_off_fixed, + traps->top.y + y_off_fixed, + traps->bot.l + x_off_fixed, + traps->bot.y + y_off_fixed); + pixman_edge_init (&r, bpp, t, - traps->top.r + x_off_fixed, - traps->top.y + y_off_fixed, - traps->bot.r + x_off_fixed, - traps->bot.y + y_off_fixed); - + traps->top.r + x_off_fixed, + traps->top.y + y_off_fixed, + traps->bot.r + x_off_fixed, + traps->bot.y + y_off_fixed); + pixman_rasterize_edges (image, &l, &r, t, b); } + traps++; } } +#if 0 static void dump_image (pixman_image_t *image, - const char *title) + const char * title) { int i, j; - + if (!image->type == BITS) - { printf ("%s is not a regular image\n", title); - } if (!image->bits.format == PIXMAN_a8) - { printf ("%s is not an alpha mask\n", title); - } printf ("\n\n\n%s: \n", title); - + for (i = 0; i < image->bits.height; ++i) { uint8_t *line = (uint8_t *)&(image->bits.bits[i * image->bits.rowstride]); - + for (j = 0; j < image->bits.width; ++j) - printf ("%c", line[j]? '#' : ' '); + printf ("%c", line[j] ? '#' : ' '); printf ("\n"); } } +#endif PIXMAN_EXPORT void -pixman_add_trapezoids (pixman_image_t *image, - int16_t x_off, - int y_off, - int ntraps, - const pixman_trapezoid_t *traps) +pixman_add_trapezoids (pixman_image_t * image, + int16_t x_off, + int y_off, + int ntraps, + const pixman_trapezoid_t *traps) { int i; #if 0 dump_image (image, "before"); #endif - + for (i = 0; i < ntraps; ++i) { const pixman_trapezoid_t *trap = &(traps[i]); - + if (!pixman_trapezoid_valid (trap)) continue; - + pixman_rasterize_trapezoid (image, trap, x_off, y_off); } @@ -144,31 +341,32 @@ pixman_add_trapezoids (pixman_image_t *image, } PIXMAN_EXPORT void -pixman_rasterize_trapezoid (pixman_image_t * image, - const pixman_trapezoid_t *trap, - int x_off, - int y_off) +pixman_rasterize_trapezoid (pixman_image_t * image, + const pixman_trapezoid_t *trap, + int x_off, + int y_off) { - int bpp; - int width; - int height; + int bpp; + int width; + int height; - pixman_fixed_t x_off_fixed; - pixman_fixed_t y_off_fixed; - pixman_edge_t l, r; - pixman_fixed_t t, b; + pixman_fixed_t x_off_fixed; + pixman_fixed_t y_off_fixed; + pixman_edge_t l, r; + pixman_fixed_t t, b; return_if_fail (image->type == BITS); - + if (!pixman_trapezoid_valid (trap)) return; width = image->bits.width; height = image->bits.height; bpp = PIXMAN_FORMAT_BPP (image->bits.format); - - x_off_fixed = pixman_int_to_fixed(x_off); - y_off_fixed = pixman_int_to_fixed(y_off); + + x_off_fixed = pixman_int_to_fixed (x_off); + y_off_fixed = pixman_int_to_fixed (y_off); + t = trap->top + y_off_fixed; if (t < 0) t = 0; @@ -178,7 +376,7 @@ pixman_rasterize_trapezoid (pixman_image_t * image, if (pixman_fixed_to_int (b) >= height) b = pixman_int_to_fixed (height) - 1; b = pixman_sample_floor_y (b, bpp); - + if (b >= t) { /* initialize edge walkers */ @@ -188,97 +386,3 @@ pixman_rasterize_trapezoid (pixman_image_t * image, pixman_rasterize_edges (image, &l, &r, t, b); } } - -#if 0 -static int -_GreaterY (pixman_point_fixed_t *a, pixman_point_fixed_t *b) -{ - if (a->y == b->y) - return a->x > b->x; - return a->y > b->y; -} - -/* - * Note that the definition of this function is a bit odd because - * of the X coordinate space (y increasing downwards). - */ -static int -_Clockwise (pixman_point_fixed_t *ref, pixman_point_fixed_t *a, pixman_point_fixed_t *b) -{ - pixman_point_fixed_t ad, bd; - - ad.x = a->x - ref->x; - ad.y = a->y - ref->y; - bd.x = b->x - ref->x; - bd.y = b->y - ref->y; - - return ((pixman_fixed_32_32_t) bd.y * ad.x - (pixman_fixed_32_32_t) ad.y * bd.x) < 0; -} - -/* FIXME -- this could be made more efficient */ -void -fbAddTriangles (pixman_image_t * pPicture, - int16_t x_off, - int16_t y_off, - int ntri, - xTriangle *tris) -{ - pixman_point_fixed_t *top, *left, *right, *tmp; - xTrapezoid trap; - - for (; ntri; ntri--, tris++) - { - top = &tris->p1; - left = &tris->p2; - right = &tris->p3; - if (_GreaterY (top, left)) { - tmp = left; left = top; top = tmp; - } - if (_GreaterY (top, right)) { - tmp = right; right = top; top = tmp; - } - if (_Clockwise (top, right, left)) { - tmp = right; right = left; left = tmp; - } - - /* - * Two cases: - * - * + + - * / \ / \ - * / \ / \ - * / + + \ - * / -- -- \ - * / -- -- \ - * / --- --- \ - * +-- --+ - */ - - trap.top = top->y; - trap.left.p1 = *top; - trap.left.p2 = *left; - trap.right.p1 = *top; - trap.right.p2 = *right; - if (right->y < left->y) - trap.bottom = right->y; - else - trap.bottom = left->y; - fbRasterizeTrapezoid (pPicture, &trap, x_off, y_off); - if (right->y < left->y) - { - trap.top = right->y; - trap.bottom = left->y; - trap.right.p1 = *right; - trap.right.p2 = *left; - } - else - { - trap.top = left->y; - trap.bottom = right->y; - trap.left.p1 = *left; - trap.left.p2 = *right; - } - fbRasterizeTrapezoid (pPicture, &trap, x_off, y_off); - } -} -#endif |