michael@0: /* michael@0: * Copyright © 2004 Keith Packard michael@0: * michael@0: * Permission to use, copy, modify, distribute, and sell this software and its michael@0: * documentation for any purpose is hereby granted without fee, provided that michael@0: * the above copyright notice appear in all copies and that both that michael@0: * copyright notice and this permission notice appear in supporting michael@0: * documentation, and that the name of Keith Packard not be used in michael@0: * advertising or publicity pertaining to distribution of the software without michael@0: * specific, written prior permission. Keith Packard makes no michael@0: * representations about the suitability of this software for any purpose. It michael@0: * is provided "as is" without express or implied warranty. michael@0: * michael@0: * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, michael@0: * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO michael@0: * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR michael@0: * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, michael@0: * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER michael@0: * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR michael@0: * PERFORMANCE OF THIS SOFTWARE. michael@0: */ michael@0: michael@0: #ifndef rasterize_span michael@0: #endif michael@0: michael@0: static void michael@0: RASTERIZE_EDGES (pixman_image_t *image, michael@0: pixman_edge_t *l, michael@0: pixman_edge_t *r, michael@0: pixman_fixed_t t, michael@0: pixman_fixed_t b) michael@0: { michael@0: pixman_fixed_t y = t; michael@0: uint32_t *line; michael@0: uint32_t *buf = (image)->bits.bits; michael@0: int stride = (image)->bits.rowstride; michael@0: int width = (image)->bits.width; michael@0: michael@0: line = buf + pixman_fixed_to_int (y) * stride; michael@0: michael@0: for (;;) michael@0: { michael@0: pixman_fixed_t lx; michael@0: pixman_fixed_t rx; michael@0: int lxi; michael@0: int rxi; michael@0: michael@0: lx = l->x; michael@0: rx = r->x; michael@0: #if N_BITS == 1 michael@0: /* For the non-antialiased case, round the coordinates up, in effect michael@0: * sampling just slightly to the left of the pixel. This is so that michael@0: * when the sample point lies exactly on the line, we round towards michael@0: * north-west. michael@0: * michael@0: * (The AA case does a similar adjustment in RENDER_SAMPLES_X) michael@0: */ michael@0: lx += X_FRAC_FIRST(1) - pixman_fixed_e; michael@0: rx += X_FRAC_FIRST(1) - pixman_fixed_e; michael@0: #endif michael@0: /* clip X */ michael@0: if (lx < 0) michael@0: lx = 0; michael@0: if (pixman_fixed_to_int (rx) >= width) michael@0: #if N_BITS == 1 michael@0: rx = pixman_int_to_fixed (width); michael@0: #else michael@0: /* Use the last pixel of the scanline, covered 100%. michael@0: * We can't use the first pixel following the scanline, michael@0: * because accessing it could result in a buffer overrun. michael@0: */ michael@0: rx = pixman_int_to_fixed (width) - 1; michael@0: #endif michael@0: michael@0: /* Skip empty (or backwards) sections */ michael@0: if (rx > lx) michael@0: { michael@0: michael@0: /* Find pixel bounds for span */ michael@0: lxi = pixman_fixed_to_int (lx); michael@0: rxi = pixman_fixed_to_int (rx); michael@0: michael@0: #if N_BITS == 1 michael@0: { michael@0: michael@0: #define LEFT_MASK(x) \ michael@0: (((x) & 0x1f) ? \ michael@0: SCREEN_SHIFT_RIGHT (0xffffffff, (x) & 0x1f) : 0) michael@0: #define RIGHT_MASK(x) \ michael@0: (((32 - (x)) & 0x1f) ? \ michael@0: SCREEN_SHIFT_LEFT (0xffffffff, (32 - (x)) & 0x1f) : 0) michael@0: michael@0: #define MASK_BITS(x,w,l,n,r) { \ michael@0: n = (w); \ michael@0: r = RIGHT_MASK ((x) + n); \ michael@0: l = LEFT_MASK (x); \ michael@0: if (l) { \ michael@0: n -= 32 - ((x) & 0x1f); \ michael@0: if (n < 0) { \ michael@0: n = 0; \ michael@0: l &= r; \ michael@0: r = 0; \ michael@0: } \ michael@0: } \ michael@0: n >>= 5; \ michael@0: } michael@0: michael@0: uint32_t *a = line; michael@0: uint32_t startmask; michael@0: uint32_t endmask; michael@0: int nmiddle; michael@0: int width = rxi - lxi; michael@0: int x = lxi; michael@0: michael@0: a += x >> 5; michael@0: x &= 0x1f; michael@0: michael@0: MASK_BITS (x, width, startmask, nmiddle, endmask); michael@0: michael@0: if (startmask) { michael@0: WRITE(image, a, READ(image, a) | startmask); michael@0: a++; michael@0: } michael@0: while (nmiddle--) michael@0: WRITE(image, a++, 0xffffffff); michael@0: if (endmask) michael@0: WRITE(image, a, READ(image, a) | endmask); michael@0: } michael@0: #else michael@0: { michael@0: DEFINE_ALPHA(line,lxi); michael@0: int lxs; michael@0: int rxs; michael@0: michael@0: /* Sample coverage for edge pixels */ michael@0: lxs = RENDER_SAMPLES_X (lx, N_BITS); michael@0: rxs = RENDER_SAMPLES_X (rx, N_BITS); michael@0: michael@0: /* Add coverage across row */ michael@0: if (lxi == rxi) michael@0: { michael@0: ADD_ALPHA (rxs - lxs); michael@0: } michael@0: else michael@0: { michael@0: int xi; michael@0: michael@0: ADD_ALPHA (N_X_FRAC(N_BITS) - lxs); michael@0: STEP_ALPHA; michael@0: for (xi = lxi + 1; xi < rxi; xi++) michael@0: { michael@0: ADD_ALPHA (N_X_FRAC(N_BITS)); michael@0: STEP_ALPHA; michael@0: } michael@0: ADD_ALPHA (rxs); michael@0: } michael@0: } michael@0: #endif michael@0: } michael@0: michael@0: if (y == b) michael@0: break; michael@0: michael@0: #if N_BITS > 1 michael@0: if (pixman_fixed_frac (y) != Y_FRAC_LAST(N_BITS)) michael@0: { michael@0: RENDER_EDGE_STEP_SMALL (l); michael@0: RENDER_EDGE_STEP_SMALL (r); michael@0: y += STEP_Y_SMALL(N_BITS); michael@0: } michael@0: else michael@0: #endif michael@0: { michael@0: RENDER_EDGE_STEP_BIG (l); michael@0: RENDER_EDGE_STEP_BIG (r); michael@0: y += STEP_Y_BIG(N_BITS); michael@0: line += stride; michael@0: } michael@0: } michael@0: } michael@0: michael@0: #undef rasterize_span