diff options
Diffstat (limited to 'pixman/pixman/pixman-edge.c')
-rw-r--r-- | pixman/pixman/pixman-edge.c | 768 |
1 files changed, 384 insertions, 384 deletions
diff --git a/pixman/pixman/pixman-edge.c b/pixman/pixman/pixman-edge.c index 22b0158ba..8d498ab44 100644 --- a/pixman/pixman/pixman-edge.c +++ b/pixman/pixman/pixman-edge.c @@ -1,384 +1,384 @@ -/*
- * Copyright © 2004 Keith Packard
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of Keith Packard not be used in
- * advertising or publicity pertaining to distribution of the software without
- * specific, written prior permission. Keith Packard makes no
- * representations about the suitability of this software for any purpose. It
- * is provided "as is" without express or implied warranty.
- *
- * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <string.h>
-
-#include "pixman-private.h"
-#include "pixman-accessor.h"
-
-/*
- * Step across a small sample grid gap
- */
-#define RENDER_EDGE_STEP_SMALL(edge) \
- { \
- edge->x += edge->stepx_small; \
- edge->e += edge->dx_small; \
- if (edge->e > 0) \
- { \
- edge->e -= edge->dy; \
- edge->x += edge->signdx; \
- } \
- }
-
-/*
- * Step across a large sample grid gap
- */
-#define RENDER_EDGE_STEP_BIG(edge) \
- { \
- edge->x += edge->stepx_big; \
- edge->e += edge->dx_big; \
- if (edge->e > 0) \
- { \
- edge->e -= edge->dy; \
- edge->x += edge->signdx; \
- } \
- }
-
-#ifdef PIXMAN_FB_ACCESSORS
-#define PIXMAN_RASTERIZE_EDGES pixman_rasterize_edges_accessors
-#else
-#define PIXMAN_RASTERIZE_EDGES pixman_rasterize_edges_no_accessors
-#endif
-
-/*
- * 4 bit alpha
- */
-
-#define N_BITS 4
-#define RASTERIZE_EDGES rasterize_edges_4
-
-#ifndef WORDS_BIGENDIAN
-#define SHIFT_4(o) ((o) << 2)
-#else
-#define SHIFT_4(o) ((1 - (o)) << 2)
-#endif
-
-#define GET_4(x, o) (((x) >> SHIFT_4 (o)) & 0xf)
-#define PUT_4(x, o, v) \
- (((x) & ~(0xf << SHIFT_4 (o))) | (((v) & 0xf) << SHIFT_4 (o)))
-
-#define DEFINE_ALPHA(line, x) \
- uint8_t *__ap = (uint8_t *) line + ((x) >> 1); \
- int __ao = (x) & 1
-
-#define STEP_ALPHA ((__ap += __ao), (__ao ^= 1))
-
-#define ADD_ALPHA(a) \
- { \
- uint8_t __o = READ (image, __ap); \
- uint8_t __a = (a) + GET_4 (__o, __ao); \
- WRITE (image, __ap, PUT_4 (__o, __ao, __a | (0 - ((__a) >> 4)))); \
- }
-
-#include "pixman-edge-imp.h"
-
-#undef ADD_ALPHA
-#undef STEP_ALPHA
-#undef DEFINE_ALPHA
-#undef RASTERIZE_EDGES
-#undef N_BITS
-
-
-/*
- * 1 bit alpha
- */
-
-#define N_BITS 1
-#define RASTERIZE_EDGES rasterize_edges_1
-
-#include "pixman-edge-imp.h"
-
-#undef RASTERIZE_EDGES
-#undef N_BITS
-
-/*
- * 8 bit alpha
- */
-
-static force_inline uint8_t
-clip255 (int x)
-{
- if (x > 255)
- return 255;
-
- return x;
-}
-
-#define ADD_SATURATE_8(buf, val, length) \
- do \
- { \
- int i__ = (length); \
- uint8_t *buf__ = (buf); \
- int val__ = (val); \
- \
- while (i__--) \
- { \
- WRITE (image, (buf__), clip255 (READ (image, (buf__)) + (val__))); \
- (buf__)++; \
- } \
- } while (0)
-
-/*
- * We want to detect the case where we add the same value to a long
- * span of pixels. The triangles on the end are filled in while we
- * count how many sub-pixel scanlines contribute to the middle section.
- *
- * +--------------------------+
- * fill_height =| \ /
- * +------------------+
- * |================|
- * fill_start fill_end
- */
-static void
-rasterize_edges_8 (pixman_image_t *image,
- pixman_edge_t * l,
- pixman_edge_t * r,
- pixman_fixed_t t,
- pixman_fixed_t b)
-{
- pixman_fixed_t y = t;
- uint32_t *line;
- int fill_start = -1, fill_end = -1;
- int fill_size = 0;
- uint32_t *buf = (image)->bits.bits;
- int stride = (image)->bits.rowstride;
- int width = (image)->bits.width;
-
- line = buf + pixman_fixed_to_int (y) * stride;
-
- for (;;)
- {
- uint8_t *ap = (uint8_t *) line;
- pixman_fixed_t lx, rx;
- int lxi, rxi;
-
- /* clip X */
- lx = l->x;
- if (lx < 0)
- lx = 0;
-
- rx = r->x;
-
- if (pixman_fixed_to_int (rx) >= width)
- {
- /* Use the last pixel of the scanline, covered 100%.
- * We can't use the first pixel following the scanline,
- * because accessing it could result in a buffer overrun.
- */
- rx = pixman_int_to_fixed (width) - 1;
- }
-
- /* Skip empty (or backwards) sections */
- if (rx > lx)
- {
- int lxs, rxs;
-
- /* Find pixel bounds for span. */
- lxi = pixman_fixed_to_int (lx);
- rxi = pixman_fixed_to_int (rx);
-
- /* Sample coverage for edge pixels */
- lxs = RENDER_SAMPLES_X (lx, 8);
- rxs = RENDER_SAMPLES_X (rx, 8);
-
- /* Add coverage across row */
- if (lxi == rxi)
- {
- WRITE (image, ap + lxi,
- clip255 (READ (image, ap + lxi) + rxs - lxs));
- }
- else
- {
- WRITE (image, ap + lxi,
- clip255 (READ (image, ap + lxi) + N_X_FRAC (8) - lxs));
-
- /* Move forward so that lxi/rxi is the pixel span */
- lxi++;
-
- /* Don't bother trying to optimize the fill unless
- * the span is longer than 4 pixels. */
- if (rxi - lxi > 4)
- {
- if (fill_start < 0)
- {
- fill_start = lxi;
- fill_end = rxi;
- fill_size++;
- }
- else
- {
- if (lxi >= fill_end || rxi < fill_start)
- {
- /* We're beyond what we saved, just fill it */
- ADD_SATURATE_8 (ap + fill_start,
- fill_size * N_X_FRAC (8),
- fill_end - fill_start);
- fill_start = lxi;
- fill_end = rxi;
- fill_size = 1;
- }
- else
- {
- /* Update fill_start */
- if (lxi > fill_start)
- {
- ADD_SATURATE_8 (ap + fill_start,
- fill_size * N_X_FRAC (8),
- lxi - fill_start);
- fill_start = lxi;
- }
- else if (lxi < fill_start)
- {
- ADD_SATURATE_8 (ap + lxi, N_X_FRAC (8),
- fill_start - lxi);
- }
-
- /* Update fill_end */
- if (rxi < fill_end)
- {
- ADD_SATURATE_8 (ap + rxi,
- fill_size * N_X_FRAC (8),
- fill_end - rxi);
- fill_end = rxi;
- }
- else if (fill_end < rxi)
- {
- ADD_SATURATE_8 (ap + fill_end,
- N_X_FRAC (8),
- rxi - fill_end);
- }
- fill_size++;
- }
- }
- }
- else
- {
- ADD_SATURATE_8 (ap + lxi, N_X_FRAC (8), rxi - lxi);
- }
-
- WRITE (image, ap + rxi, clip255 (READ (image, ap + rxi) + rxs));
- }
- }
-
- if (y == b)
- {
- /* We're done, make sure we clean up any remaining fill. */
- if (fill_start != fill_end)
- {
- if (fill_size == N_Y_FRAC (8))
- {
- MEMSET_WRAPPED (image, ap + fill_start,
- 0xff, fill_end - fill_start);
- }
- else
- {
- ADD_SATURATE_8 (ap + fill_start, fill_size * N_X_FRAC (8),
- fill_end - fill_start);
- }
- }
- break;
- }
-
- if (pixman_fixed_frac (y) != Y_FRAC_LAST (8))
- {
- RENDER_EDGE_STEP_SMALL (l);
- RENDER_EDGE_STEP_SMALL (r);
- y += STEP_Y_SMALL (8);
- }
- else
- {
- RENDER_EDGE_STEP_BIG (l);
- RENDER_EDGE_STEP_BIG (r);
- y += STEP_Y_BIG (8);
- if (fill_start != fill_end)
- {
- if (fill_size == N_Y_FRAC (8))
- {
- MEMSET_WRAPPED (image, ap + fill_start,
- 0xff, fill_end - fill_start);
- }
- else
- {
- ADD_SATURATE_8 (ap + fill_start, fill_size * N_X_FRAC (8),
- fill_end - fill_start);
- }
-
- fill_start = fill_end = -1;
- fill_size = 0;
- }
-
- line += stride;
- }
- }
-}
-
-#ifndef PIXMAN_FB_ACCESSORS
-static
-#endif
-void
-PIXMAN_RASTERIZE_EDGES (pixman_image_t *image,
- pixman_edge_t * l,
- pixman_edge_t * r,
- pixman_fixed_t t,
- pixman_fixed_t b)
-{
- switch (PIXMAN_FORMAT_BPP (image->bits.format))
- {
- case 1:
- rasterize_edges_1 (image, l, r, t, b);
- break;
-
- case 4:
- rasterize_edges_4 (image, l, r, t, b);
- break;
-
- case 8:
- rasterize_edges_8 (image, l, r, t, b);
- break;
-
- default:
- break;
- }
-}
-
-#ifndef PIXMAN_FB_ACCESSORS
-
-PIXMAN_EXPORT void
-pixman_rasterize_edges (pixman_image_t *image,
- pixman_edge_t * l,
- pixman_edge_t * r,
- pixman_fixed_t t,
- pixman_fixed_t b)
-{
- return_if_fail (image->type == BITS);
-
- if (image->bits.read_func || image->bits.write_func)
- pixman_rasterize_edges_accessors (image, l, r, t, b);
- else
- pixman_rasterize_edges_no_accessors (image, l, r, t, b);
-}
-
-#endif
+/* + * Copyright © 2004 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <string.h> + +#include "pixman-private.h" +#include "pixman-accessor.h" + +/* + * Step across a small sample grid gap + */ +#define RENDER_EDGE_STEP_SMALL(edge) \ + { \ + edge->x += edge->stepx_small; \ + edge->e += edge->dx_small; \ + if (edge->e > 0) \ + { \ + edge->e -= edge->dy; \ + edge->x += edge->signdx; \ + } \ + } + +/* + * Step across a large sample grid gap + */ +#define RENDER_EDGE_STEP_BIG(edge) \ + { \ + edge->x += edge->stepx_big; \ + edge->e += edge->dx_big; \ + if (edge->e > 0) \ + { \ + edge->e -= edge->dy; \ + edge->x += edge->signdx; \ + } \ + } + +#ifdef PIXMAN_FB_ACCESSORS +#define PIXMAN_RASTERIZE_EDGES pixman_rasterize_edges_accessors +#else +#define PIXMAN_RASTERIZE_EDGES pixman_rasterize_edges_no_accessors +#endif + +/* + * 4 bit alpha + */ + +#define N_BITS 4 +#define RASTERIZE_EDGES rasterize_edges_4 + +#ifndef WORDS_BIGENDIAN +#define SHIFT_4(o) ((o) << 2) +#else +#define SHIFT_4(o) ((1 - (o)) << 2) +#endif + +#define GET_4(x, o) (((x) >> SHIFT_4 (o)) & 0xf) +#define PUT_4(x, o, v) \ + (((x) & ~(0xf << SHIFT_4 (o))) | (((v) & 0xf) << SHIFT_4 (o))) + +#define DEFINE_ALPHA(line, x) \ + uint8_t *__ap = (uint8_t *) line + ((x) >> 1); \ + int __ao = (x) & 1 + +#define STEP_ALPHA ((__ap += __ao), (__ao ^= 1)) + +#define ADD_ALPHA(a) \ + { \ + uint8_t __o = READ (image, __ap); \ + uint8_t __a = (a) + GET_4 (__o, __ao); \ + WRITE (image, __ap, PUT_4 (__o, __ao, __a | (0 - ((__a) >> 4)))); \ + } + +#include "pixman-edge-imp.h" + +#undef ADD_ALPHA +#undef STEP_ALPHA +#undef DEFINE_ALPHA +#undef RASTERIZE_EDGES +#undef N_BITS + + +/* + * 1 bit alpha + */ + +#define N_BITS 1 +#define RASTERIZE_EDGES rasterize_edges_1 + +#include "pixman-edge-imp.h" + +#undef RASTERIZE_EDGES +#undef N_BITS + +/* + * 8 bit alpha + */ + +static force_inline uint8_t +clip255 (int x) +{ + if (x > 255) + return 255; + + return x; +} + +#define ADD_SATURATE_8(buf, val, length) \ + do \ + { \ + int i__ = (length); \ + uint8_t *buf__ = (buf); \ + int val__ = (val); \ + \ + while (i__--) \ + { \ + WRITE (image, (buf__), clip255 (READ (image, (buf__)) + (val__))); \ + (buf__)++; \ + } \ + } while (0) + +/* + * We want to detect the case where we add the same value to a long + * span of pixels. The triangles on the end are filled in while we + * count how many sub-pixel scanlines contribute to the middle section. + * + * +--------------------------+ + * fill_height =| \ / + * +------------------+ + * |================| + * fill_start fill_end + */ +static void +rasterize_edges_8 (pixman_image_t *image, + pixman_edge_t * l, + pixman_edge_t * r, + pixman_fixed_t t, + pixman_fixed_t b) +{ + pixman_fixed_t y = t; + uint32_t *line; + int fill_start = -1, fill_end = -1; + int fill_size = 0; + uint32_t *buf = (image)->bits.bits; + int stride = (image)->bits.rowstride; + int width = (image)->bits.width; + + line = buf + pixman_fixed_to_int (y) * stride; + + for (;;) + { + uint8_t *ap = (uint8_t *) line; + pixman_fixed_t lx, rx; + int lxi, rxi; + + /* clip X */ + lx = l->x; + if (lx < 0) + lx = 0; + + rx = r->x; + + if (pixman_fixed_to_int (rx) >= width) + { + /* Use the last pixel of the scanline, covered 100%. + * We can't use the first pixel following the scanline, + * because accessing it could result in a buffer overrun. + */ + rx = pixman_int_to_fixed (width) - 1; + } + + /* Skip empty (or backwards) sections */ + if (rx > lx) + { + int lxs, rxs; + + /* Find pixel bounds for span. */ + lxi = pixman_fixed_to_int (lx); + rxi = pixman_fixed_to_int (rx); + + /* Sample coverage for edge pixels */ + lxs = RENDER_SAMPLES_X (lx, 8); + rxs = RENDER_SAMPLES_X (rx, 8); + + /* Add coverage across row */ + if (lxi == rxi) + { + WRITE (image, ap + lxi, + clip255 (READ (image, ap + lxi) + rxs - lxs)); + } + else + { + WRITE (image, ap + lxi, + clip255 (READ (image, ap + lxi) + N_X_FRAC (8) - lxs)); + + /* Move forward so that lxi/rxi is the pixel span */ + lxi++; + + /* Don't bother trying to optimize the fill unless + * the span is longer than 4 pixels. */ + if (rxi - lxi > 4) + { + if (fill_start < 0) + { + fill_start = lxi; + fill_end = rxi; + fill_size++; + } + else + { + if (lxi >= fill_end || rxi < fill_start) + { + /* We're beyond what we saved, just fill it */ + ADD_SATURATE_8 (ap + fill_start, + fill_size * N_X_FRAC (8), + fill_end - fill_start); + fill_start = lxi; + fill_end = rxi; + fill_size = 1; + } + else + { + /* Update fill_start */ + if (lxi > fill_start) + { + ADD_SATURATE_8 (ap + fill_start, + fill_size * N_X_FRAC (8), + lxi - fill_start); + fill_start = lxi; + } + else if (lxi < fill_start) + { + ADD_SATURATE_8 (ap + lxi, N_X_FRAC (8), + fill_start - lxi); + } + + /* Update fill_end */ + if (rxi < fill_end) + { + ADD_SATURATE_8 (ap + rxi, + fill_size * N_X_FRAC (8), + fill_end - rxi); + fill_end = rxi; + } + else if (fill_end < rxi) + { + ADD_SATURATE_8 (ap + fill_end, + N_X_FRAC (8), + rxi - fill_end); + } + fill_size++; + } + } + } + else + { + ADD_SATURATE_8 (ap + lxi, N_X_FRAC (8), rxi - lxi); + } + + WRITE (image, ap + rxi, clip255 (READ (image, ap + rxi) + rxs)); + } + } + + if (y == b) + { + /* We're done, make sure we clean up any remaining fill. */ + if (fill_start != fill_end) + { + if (fill_size == N_Y_FRAC (8)) + { + MEMSET_WRAPPED (image, ap + fill_start, + 0xff, fill_end - fill_start); + } + else + { + ADD_SATURATE_8 (ap + fill_start, fill_size * N_X_FRAC (8), + fill_end - fill_start); + } + } + break; + } + + if (pixman_fixed_frac (y) != Y_FRAC_LAST (8)) + { + RENDER_EDGE_STEP_SMALL (l); + RENDER_EDGE_STEP_SMALL (r); + y += STEP_Y_SMALL (8); + } + else + { + RENDER_EDGE_STEP_BIG (l); + RENDER_EDGE_STEP_BIG (r); + y += STEP_Y_BIG (8); + if (fill_start != fill_end) + { + if (fill_size == N_Y_FRAC (8)) + { + MEMSET_WRAPPED (image, ap + fill_start, + 0xff, fill_end - fill_start); + } + else + { + ADD_SATURATE_8 (ap + fill_start, fill_size * N_X_FRAC (8), + fill_end - fill_start); + } + + fill_start = fill_end = -1; + fill_size = 0; + } + + line += stride; + } + } +} + +#ifndef PIXMAN_FB_ACCESSORS +static +#endif +void +PIXMAN_RASTERIZE_EDGES (pixman_image_t *image, + pixman_edge_t * l, + pixman_edge_t * r, + pixman_fixed_t t, + pixman_fixed_t b) +{ + switch (PIXMAN_FORMAT_BPP (image->bits.format)) + { + case 1: + rasterize_edges_1 (image, l, r, t, b); + break; + + case 4: + rasterize_edges_4 (image, l, r, t, b); + break; + + case 8: + rasterize_edges_8 (image, l, r, t, b); + break; + + default: + break; + } +} + +#ifndef PIXMAN_FB_ACCESSORS + +PIXMAN_EXPORT void +pixman_rasterize_edges (pixman_image_t *image, + pixman_edge_t * l, + pixman_edge_t * r, + pixman_fixed_t t, + pixman_fixed_t b) +{ + return_if_fail (image->type == BITS); + + if (image->bits.read_func || image->bits.write_func) + pixman_rasterize_edges_accessors (image, l, r, t, b); + else + pixman_rasterize_edges_no_accessors (image, l, r, t, b); +} + +#endif |