aboutsummaryrefslogtreecommitdiff
path: root/pixman/pixman/pixman-trap.c
diff options
context:
space:
mode:
Diffstat (limited to 'pixman/pixman/pixman-trap.c')
-rw-r--r--pixman/pixman/pixman-trap.c414
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