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

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/cairo/libpixman/src/pixman-edge.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,385 @@
     1.4 +/*
     1.5 + * Copyright © 2004 Keith Packard
     1.6 + *
     1.7 + * Permission to use, copy, modify, distribute, and sell this software and its
     1.8 + * documentation for any purpose is hereby granted without fee, provided that
     1.9 + * the above copyright notice appear in all copies and that both that
    1.10 + * copyright notice and this permission notice appear in supporting
    1.11 + * documentation, and that the name of Keith Packard not be used in
    1.12 + * advertising or publicity pertaining to distribution of the software without
    1.13 + * specific, written prior permission.  Keith Packard makes no
    1.14 + * representations about the suitability of this software for any purpose.  It
    1.15 + * is provided "as is" without express or implied warranty.
    1.16 + *
    1.17 + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
    1.18 + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
    1.19 + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
    1.20 + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
    1.21 + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
    1.22 + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
    1.23 + * PERFORMANCE OF THIS SOFTWARE.
    1.24 + */
    1.25 +
    1.26 +#ifdef HAVE_CONFIG_H
    1.27 +#include <config.h>
    1.28 +#endif
    1.29 +
    1.30 +#include <string.h>
    1.31 +
    1.32 +#include "pixman-private.h"
    1.33 +#include "pixman-accessor.h"
    1.34 +
    1.35 +/*
    1.36 + * Step across a small sample grid gap
    1.37 + */
    1.38 +#define RENDER_EDGE_STEP_SMALL(edge)					\
    1.39 +    {									\
    1.40 +	edge->x += edge->stepx_small;					\
    1.41 +	edge->e += edge->dx_small;					\
    1.42 +	if (edge->e > 0)						\
    1.43 +	{								\
    1.44 +	    edge->e -= edge->dy;					\
    1.45 +	    edge->x += edge->signdx;					\
    1.46 +	}								\
    1.47 +    }
    1.48 +
    1.49 +/*
    1.50 + * Step across a large sample grid gap
    1.51 + */
    1.52 +#define RENDER_EDGE_STEP_BIG(edge)					\
    1.53 +    {									\
    1.54 +	edge->x += edge->stepx_big;					\
    1.55 +	edge->e += edge->dx_big;					\
    1.56 +	if (edge->e > 0)						\
    1.57 +	{								\
    1.58 +	    edge->e -= edge->dy;					\
    1.59 +	    edge->x += edge->signdx;					\
    1.60 +	}								\
    1.61 +    }
    1.62 +
    1.63 +#ifdef PIXMAN_FB_ACCESSORS
    1.64 +#define PIXMAN_RASTERIZE_EDGES pixman_rasterize_edges_accessors
    1.65 +#else
    1.66 +#define PIXMAN_RASTERIZE_EDGES pixman_rasterize_edges_no_accessors
    1.67 +#endif
    1.68 +
    1.69 +/*
    1.70 + * 4 bit alpha
    1.71 + */
    1.72 +
    1.73 +#define N_BITS  4
    1.74 +#define RASTERIZE_EDGES rasterize_edges_4
    1.75 +
    1.76 +#ifndef WORDS_BIGENDIAN
    1.77 +#define SHIFT_4(o)      ((o) << 2)
    1.78 +#else
    1.79 +#define SHIFT_4(o)      ((1 - (o)) << 2)
    1.80 +#endif
    1.81 +
    1.82 +#define GET_4(x, o)      (((x) >> SHIFT_4 (o)) & 0xf)
    1.83 +#define PUT_4(x, o, v)							\
    1.84 +    (((x) & ~(0xf << SHIFT_4 (o))) | (((v) & 0xf) << SHIFT_4 (o)))
    1.85 +
    1.86 +#define DEFINE_ALPHA(line, x)						\
    1.87 +    uint8_t   *__ap = (uint8_t *) line + ((x) >> 1);			\
    1.88 +    int __ao = (x) & 1
    1.89 +
    1.90 +#define STEP_ALPHA      ((__ap += __ao), (__ao ^= 1))
    1.91 +
    1.92 +#define ADD_ALPHA(a)							\
    1.93 +    {									\
    1.94 +        uint8_t __o = READ (image, __ap);				\
    1.95 +        uint8_t __a = (a) + GET_4 (__o, __ao);				\
    1.96 +        WRITE (image, __ap, PUT_4 (__o, __ao, __a | (0 - ((__a) >> 4)))); \
    1.97 +    }
    1.98 +
    1.99 +#include "pixman-edge-imp.h"
   1.100 +
   1.101 +#undef ADD_ALPHA
   1.102 +#undef STEP_ALPHA
   1.103 +#undef DEFINE_ALPHA
   1.104 +#undef RASTERIZE_EDGES
   1.105 +#undef N_BITS
   1.106 +
   1.107 +
   1.108 +/*
   1.109 + * 1 bit alpha
   1.110 + */
   1.111 +
   1.112 +#define N_BITS 1
   1.113 +#define RASTERIZE_EDGES rasterize_edges_1
   1.114 +
   1.115 +#include "pixman-edge-imp.h"
   1.116 +
   1.117 +#undef RASTERIZE_EDGES
   1.118 +#undef N_BITS
   1.119 +
   1.120 +/*
   1.121 + * 8 bit alpha
   1.122 + */
   1.123 +
   1.124 +static force_inline uint8_t
   1.125 +clip255 (int x)
   1.126 +{
   1.127 +    if (x > 255)
   1.128 +	return 255;
   1.129 +
   1.130 +    return x;
   1.131 +}
   1.132 +
   1.133 +#define ADD_SATURATE_8(buf, val, length)				\
   1.134 +    do									\
   1.135 +    {									\
   1.136 +        int i__ = (length);						\
   1.137 +        uint8_t *buf__ = (buf);						\
   1.138 +        int val__ = (val);						\
   1.139 +									\
   1.140 +        while (i__--)							\
   1.141 +        {								\
   1.142 +            WRITE (image, (buf__), clip255 (READ (image, (buf__)) + (val__))); \
   1.143 +            (buf__)++;							\
   1.144 +	}								\
   1.145 +    } while (0)
   1.146 +
   1.147 +/*
   1.148 + * We want to detect the case where we add the same value to a long
   1.149 + * span of pixels.  The triangles on the end are filled in while we
   1.150 + * count how many sub-pixel scanlines contribute to the middle section.
   1.151 + *
   1.152 + *                 +--------------------------+
   1.153 + *  fill_height =|   \                      /
   1.154 + *                     +------------------+
   1.155 + *                      |================|
   1.156 + *                   fill_start       fill_end
   1.157 + */
   1.158 +static void
   1.159 +rasterize_edges_8 (pixman_image_t *image,
   1.160 +                   pixman_edge_t * l,
   1.161 +                   pixman_edge_t * r,
   1.162 +                   pixman_fixed_t  t,
   1.163 +                   pixman_fixed_t  b)
   1.164 +{
   1.165 +    pixman_fixed_t y = t;
   1.166 +    uint32_t  *line;
   1.167 +    int fill_start = -1, fill_end = -1;
   1.168 +    int fill_size = 0;
   1.169 +    uint32_t *buf = (image)->bits.bits;
   1.170 +    int stride = (image)->bits.rowstride;
   1.171 +    int width = (image)->bits.width;
   1.172 +
   1.173 +    line = buf + pixman_fixed_to_int (y) * stride;
   1.174 +
   1.175 +    for (;;)
   1.176 +    {
   1.177 +        uint8_t *ap = (uint8_t *) line;
   1.178 +        pixman_fixed_t lx, rx;
   1.179 +        int lxi, rxi;
   1.180 +
   1.181 +        /* clip X */
   1.182 +        lx = l->x;
   1.183 +        if (lx < 0)
   1.184 +	    lx = 0;
   1.185 +
   1.186 +        rx = r->x;
   1.187 +
   1.188 +        if (pixman_fixed_to_int (rx) >= width)
   1.189 +	{
   1.190 +	    /* Use the last pixel of the scanline, covered 100%.
   1.191 +	     * We can't use the first pixel following the scanline,
   1.192 +	     * because accessing it could result in a buffer overrun.
   1.193 +	     */
   1.194 +	    rx = pixman_int_to_fixed (width) - 1;
   1.195 +	}
   1.196 +
   1.197 +        /* Skip empty (or backwards) sections */
   1.198 +        if (rx > lx)
   1.199 +        {
   1.200 +            int lxs, rxs;
   1.201 +
   1.202 +            /* Find pixel bounds for span. */
   1.203 +            lxi = pixman_fixed_to_int (lx);
   1.204 +            rxi = pixman_fixed_to_int (rx);
   1.205 +
   1.206 +            /* Sample coverage for edge pixels */
   1.207 +            lxs = RENDER_SAMPLES_X (lx, 8);
   1.208 +            rxs = RENDER_SAMPLES_X (rx, 8);
   1.209 +
   1.210 +            /* Add coverage across row */
   1.211 +            if (lxi == rxi)
   1.212 +            {
   1.213 +                WRITE (image, ap + lxi,
   1.214 +		       clip255 (READ (image, ap + lxi) + rxs - lxs));
   1.215 +	    }
   1.216 +            else
   1.217 +            {
   1.218 +                WRITE (image, ap + lxi,
   1.219 +		       clip255 (READ (image, ap + lxi) + N_X_FRAC (8) - lxs));
   1.220 +
   1.221 +                /* Move forward so that lxi/rxi is the pixel span */
   1.222 +                lxi++;
   1.223 +
   1.224 +                /* Don't bother trying to optimize the fill unless
   1.225 +		 * the span is longer than 4 pixels. */
   1.226 +                if (rxi - lxi > 4)
   1.227 +                {
   1.228 +                    if (fill_start < 0)
   1.229 +                    {
   1.230 +                        fill_start = lxi;
   1.231 +                        fill_end = rxi;
   1.232 +                        fill_size++;
   1.233 +		    }
   1.234 +                    else
   1.235 +                    {
   1.236 +                        if (lxi >= fill_end || rxi < fill_start)
   1.237 +                        {
   1.238 +                            /* We're beyond what we saved, just fill it */
   1.239 +                            ADD_SATURATE_8 (ap + fill_start,
   1.240 +                                            fill_size * N_X_FRAC (8),
   1.241 +                                            fill_end - fill_start);
   1.242 +                            fill_start = lxi;
   1.243 +                            fill_end = rxi;
   1.244 +                            fill_size = 1;
   1.245 +			}
   1.246 +                        else
   1.247 +                        {
   1.248 +                            /* Update fill_start */
   1.249 +                            if (lxi > fill_start)
   1.250 +                            {
   1.251 +                                ADD_SATURATE_8 (ap + fill_start,
   1.252 +                                                fill_size * N_X_FRAC (8),
   1.253 +                                                lxi - fill_start);
   1.254 +                                fill_start = lxi;
   1.255 +			    }
   1.256 +                            else if (lxi < fill_start)
   1.257 +                            {
   1.258 +                                ADD_SATURATE_8 (ap + lxi, N_X_FRAC (8),
   1.259 +                                                fill_start - lxi);
   1.260 +			    }
   1.261 +
   1.262 +                            /* Update fill_end */
   1.263 +                            if (rxi < fill_end)
   1.264 +                            {
   1.265 +                                ADD_SATURATE_8 (ap + rxi,
   1.266 +                                                fill_size * N_X_FRAC (8),
   1.267 +                                                fill_end - rxi);
   1.268 +                                fill_end = rxi;
   1.269 +			    }
   1.270 +                            else if (fill_end < rxi)
   1.271 +                            {
   1.272 +                                ADD_SATURATE_8 (ap + fill_end,
   1.273 +                                                N_X_FRAC (8),
   1.274 +                                                rxi - fill_end);
   1.275 +			    }
   1.276 +                            fill_size++;
   1.277 +			}
   1.278 +		    }
   1.279 +		}
   1.280 +                else
   1.281 +                {
   1.282 +                    ADD_SATURATE_8 (ap + lxi, N_X_FRAC (8), rxi - lxi);
   1.283 +		}
   1.284 +
   1.285 +                WRITE (image, ap + rxi, clip255 (READ (image, ap + rxi) + rxs));
   1.286 +	    }
   1.287 +	}
   1.288 +
   1.289 +        if (y == b)
   1.290 +        {
   1.291 +            /* We're done, make sure we clean up any remaining fill. */
   1.292 +            if (fill_start != fill_end)
   1.293 +            {
   1.294 +                if (fill_size == N_Y_FRAC (8))
   1.295 +                {
   1.296 +                    MEMSET_WRAPPED (image, ap + fill_start,
   1.297 +				    0xff, fill_end - fill_start);
   1.298 +		}
   1.299 +                else
   1.300 +                {
   1.301 +                    ADD_SATURATE_8 (ap + fill_start, fill_size * N_X_FRAC (8),
   1.302 +                                    fill_end - fill_start);
   1.303 +		}
   1.304 +	    }
   1.305 +            break;
   1.306 +	}
   1.307 +
   1.308 +        if (pixman_fixed_frac (y) != Y_FRAC_LAST (8))
   1.309 +        {
   1.310 +            RENDER_EDGE_STEP_SMALL (l);
   1.311 +            RENDER_EDGE_STEP_SMALL (r);
   1.312 +            y += STEP_Y_SMALL (8);
   1.313 +	}
   1.314 +        else
   1.315 +        {
   1.316 +            RENDER_EDGE_STEP_BIG (l);
   1.317 +            RENDER_EDGE_STEP_BIG (r);
   1.318 +            y += STEP_Y_BIG (8);
   1.319 +            if (fill_start != fill_end)
   1.320 +            {
   1.321 +                if (fill_size == N_Y_FRAC (8))
   1.322 +                {
   1.323 +                    MEMSET_WRAPPED (image, ap + fill_start,
   1.324 +				    0xff, fill_end - fill_start);
   1.325 +		}
   1.326 +                else
   1.327 +                {
   1.328 +                    ADD_SATURATE_8 (ap + fill_start, fill_size * N_X_FRAC (8),
   1.329 +                                    fill_end - fill_start);
   1.330 +		}
   1.331 +		
   1.332 +                fill_start = fill_end = -1;
   1.333 +                fill_size = 0;
   1.334 +	    }
   1.335 +	    
   1.336 +            line += stride;
   1.337 +	}
   1.338 +    }
   1.339 +}
   1.340 +
   1.341 +#ifndef PIXMAN_FB_ACCESSORS
   1.342 +static
   1.343 +#endif
   1.344 +void
   1.345 +PIXMAN_RASTERIZE_EDGES (pixman_image_t *image,
   1.346 +                        pixman_edge_t * l,
   1.347 +                        pixman_edge_t * r,
   1.348 +                        pixman_fixed_t  t,
   1.349 +                        pixman_fixed_t  b)
   1.350 +{
   1.351 +    switch (PIXMAN_FORMAT_BPP (image->bits.format))
   1.352 +    {
   1.353 +    case 1:
   1.354 +	rasterize_edges_1 (image, l, r, t, b);
   1.355 +	break;
   1.356 +
   1.357 +    case 4:
   1.358 +	rasterize_edges_4 (image, l, r, t, b);
   1.359 +	break;
   1.360 +
   1.361 +    case 8:
   1.362 +	rasterize_edges_8 (image, l, r, t, b);
   1.363 +	break;
   1.364 +
   1.365 +    default:
   1.366 +        break;
   1.367 +    }
   1.368 +}
   1.369 +
   1.370 +#ifndef PIXMAN_FB_ACCESSORS
   1.371 +
   1.372 +PIXMAN_EXPORT void
   1.373 +pixman_rasterize_edges (pixman_image_t *image,
   1.374 +                        pixman_edge_t * l,
   1.375 +                        pixman_edge_t * r,
   1.376 +                        pixman_fixed_t  t,
   1.377 +                        pixman_fixed_t  b)
   1.378 +{
   1.379 +    return_if_fail (image->type == BITS);
   1.380 +    return_if_fail (PIXMAN_FORMAT_TYPE (image->bits.format) == PIXMAN_TYPE_A);
   1.381 +    
   1.382 +    if (image->bits.read_func || image->bits.write_func)
   1.383 +	pixman_rasterize_edges_accessors (image, l, r, t, b);
   1.384 +    else
   1.385 +	pixman_rasterize_edges_no_accessors (image, l, r, t, b);
   1.386 +}
   1.387 +
   1.388 +#endif

mercurial